/* * The ManaPlus Client * Copyright (C) 2004-2009 The Mana World Development Team * Copyright (C) 2009-2010 The Mana Developers * Copyright (C) 2011-2019 The ManaPlus Developers * * This file is part of The ManaPlus Client. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "gui/windows/shopwindow.h" #include "const/resources/currency.h" #ifdef TMWA_SUPPORT #include "gui/windows/buydialog.h" #include "gui/windows/chatwindow.h" #include "gui/windows/confirmdialog.h" #include "gui/windows/shopselldialog.h" #include "gui/windows/tradewindow.h" #include "const/sound.h" #include "const/gui/chat.h" #endif // TMWA_SUPPORT #include "enums/gui/layouttype.h" #include "gui/windows/editdialog.h" #include "gui/windows/itemamountwindow.h" #include "gui/windows/setupwindow.h" #include "gui/models/shopitems.h" #include "gui/widgets/button.h" #include "gui/widgets/checkbox.h" #include "gui/widgets/containerplacer.h" #include "gui/widgets/createwidget.h" #include "gui/widgets/layout.h" #include "gui/widgets/scrollarea.h" #include "gui/widgets/shoplistbox.h" #include "gui/widgets/tabstrip.h" #include "listeners/shoprenamelistener.h" #ifdef TMWA_SUPPORT #include "actormanager.h" #include "soundmanager.h" #endif // TMWA_SUPPORT #include "configuration.h" #include "settings.h" #include "being/localplayer.h" #include "being/playerinfo.h" #ifdef TMWA_SUPPORT #include "being/playerrelations.h" #include "net/chathandler.h" #endif // TMWA_SUPPORT #include "net/buyingstorehandler.h" #include "net/vendinghandler.h" #include "net/net.h" #ifdef TMWA_SUPPORT #include "net/tradehandler.h" #endif // TMWA_SUPPORT #include "utils/checkutils.h" #include "utils/delete2.h" #include "utils/foreach.h" #include "utils/gettext.h" #ifdef TMWA_SUPPORT #include "resources/iteminfo.h" #endif // TMWA_SUPPORT #include "resources/inventory/inventory.h" #include "resources/item/shopitem.h" #include #include #include #include "debug.h" ShopWindow *shopWindow = nullptr; extern std::string tradePartnerName; ShopWindow::DialogList ShopWindow::instances; ShopWindow::ShopWindow() : // TRANSLATORS: shop window name Window(_("Personal Shop"), Modal_false, nullptr, "shop.xml"), VendingModeListener(), VendingSlotsListener(), BuyingStoreModeListener(), BuyingStoreSlotsListener(), ActionListener(), SelectionListener(), // TRANSLATORS: shop window button mCloseButton(new Button(this, _("Close"), "close", BUTTON_SKIN, this)), mBuyShopItems(new ShopItems(false, DEFAULT_CURRENCY)), mSellShopItems(new ShopItems(false, DEFAULT_CURRENCY)), mTradeItem(nullptr), mBuyShopItemList(CREATEWIDGETR(ShopListBox, this, mBuyShopItems, mBuyShopItems, ShopListBoxType::BuyShop)), mSellShopItemList(CREATEWIDGETR(ShopListBox, this, mSellShopItems, mSellShopItems, ShopListBoxType::SellShop)), mCurrentShopItemList(nullptr), mScrollArea(new ScrollArea(this, mBuyShopItemList, fromBool(getOptionBool("showbuybackground", false), Opaque), "shop_buy_background.xml")), // TRANSLATORS: shop window label mAddButton(new Button(this, _("Add"), "add", BUTTON_SKIN, this)), // TRANSLATORS: shop window label mDeleteButton(new Button(this, _("Delete"), "delete", BUTTON_SKIN, this)), mAnnounceButton(nullptr), mPublishButton(nullptr), mRenameButton(nullptr), mAnnounceLinks(nullptr), mTabs(nullptr), mAcceptPlayer(), mTradeNick(), mSellShopName(serverConfig.getStringValue("sellShopName")), mSelectedItem(-1), mAnnonceTime(0), mLastRequestTimeList(0), mLastRequestTimeItem(0), mRandCounter(0), mTradeMoney(0), mSellShopSize(0), mBuyShopSize(0), isBuySelected(true), mHaveVending(Net::getNetworkType() != ServerType::TMWATHENA), mEnableBuyingStore(false), mEnableVending(false) { setWindowName("Personal Shop"); setResizable(true); setCloseButton(true); setStickyButtonLock(true); setMinWidth(300); setMinHeight(220); if (mainGraphics->mWidth > 600) setDefaultSize(500, 300, ImagePosition::CENTER, 0, 0); else setDefaultSize(380, 300, ImagePosition::CENTER, 0, 0); if (setupWindow != nullptr) setupWindow->registerWindowForReset(this); const int size = config.getIntValue("fontSize") + getOption("tabHeightAdjust", 16); mTabs = new TabStrip(this, "shop", size, 0); mTabs->addActionListener(this); mTabs->setActionEventId("tab_"); // TRANSLATORS: shop window tab name mTabs->addButton(_("Buy"), "buy", true); // TRANSLATORS: shop window tab name mTabs->addButton(_("Sell"), "sell", false); mTabs->setSelectable(false); mScrollArea->setSelectable(false); loadList(); mBuyShopItemList->setPriceCheck(false); mSellShopItemList->setPriceCheck(false); mScrollArea->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); mBuyShopItemList->addSelectionListener(this); mSellShopItemList->addSelectionListener(this); ContainerPlacer placer(nullptr, nullptr); placer = getPlacer(0, 0); placer(0, 0, mTabs, 8, 1).setPadding(3); if (mHaveVending) { mPublishButton = new Button(this, // TRANSLATORS: shop window button _("Publish"), "publish", BUTTON_SKIN, this); mRenameButton = new Button(this, // TRANSLATORS: shop window button _("Rename"), "rename", BUTTON_SKIN, this); placer(2, 6, mPublishButton, 1, 1); placer(3, 6, mRenameButton, 1, 1); } else { mAnnounceButton = new Button(this, // TRANSLATORS: shop window button _("Announce"), "announce", BUTTON_SKIN, this); // TRANSLATORS: shop window checkbox mAnnounceLinks = new CheckBox(this, _("Show links in announce"), false, this, "link announce"); placer(2, 6, mAnnounceButton, 1, 1); placer(0, 7, mAnnounceLinks, 7, 1); } placer(0, 1, mScrollArea, 8, 5).setPadding(3); placer(0, 6, mAddButton, 1, 1); placer(1, 6, mDeleteButton, 1, 1); placer(7, 6, mCloseButton, 1, 1); Layout &layout = getLayout(); layout.setRowHeight(0, LayoutType::SET); center(); loadWindowState(); updateShopName(); instances.push_back(this); } void ShopWindow::postInit() { Window::postInit(); setVisible(Visible_false); enableVisibleSound(true); updateSelection(); } ShopWindow::~ShopWindow() { saveList(); delete2(mBuyShopItemList) delete2(mSellShopItemList) delete2(mBuyShopItems) delete2(mSellShopItems) delete2(mTradeItem) instances.remove(this); } void ShopWindow::action(const ActionEvent &event) { const std::string &eventId = event.getId(); if (eventId == "close") { close(); return; } #ifdef TMWA_SUPPORT else if (eventId == "yes") { startTrade(); } else if (eventId == "no") { mTradeNick.clear(); } else if (eventId == "ignore") { playerRelations.ignoreTrade(mTradeNick); mTradeNick.clear(); } else if (eventId == "announce") { if (isBuySelected) { if (mBuyShopItems->getNumberOfElements() > 0) announce(mBuyShopItems, BUY); } else if (mSellShopItems->getNumberOfElements() > 0) { announce(mSellShopItems, SELL); } } #endif // TMWA_SUPPORT else if (eventId == "delete") { if (isBuySelected) { if (mBuyShopItemList != nullptr && mBuyShopItemList->getSelected() >= 0) { mBuyShopItems->del(mBuyShopItemList->getSelected()); if (isShopEmpty() && (localPlayer != nullptr)) localPlayer->updateStatus(); } } else if ((mSellShopItemList != nullptr) && mSellShopItemList->getSelected() >= 0) { mSellShopItems->del(mSellShopItemList->getSelected()); if (isShopEmpty() && (localPlayer != nullptr)) localPlayer->updateStatus(); } } else if (eventId == "tab_buy") { isBuySelected = true; updateSelection(); } else if (eventId == "tab_sell") { isBuySelected = false; updateSelection(); } else if (eventId == "publish") { if (isBuySelected) { if (mEnableBuyingStore) { buyingStoreHandler->close(); BuyingStoreModeListener::distributeEvent(false); } else { STD_VECTOR &items = mBuyShopItems->items(); if (!items.empty()) { buyingStoreHandler->create(mSellShopName, PlayerInfo::getAttribute(Attributes::MONEY), true, items); } } } else { if (mEnableVending) { vendingHandler->close(); VendingModeListener::distributeEvent(false); } else { STD_VECTOR &oldItems = mSellShopItems->items(); STD_VECTOR items; const Inventory *const inv = PlayerInfo::getCartInventory(); if (inv == nullptr) return; FOR_EACH (STD_VECTOR::iterator, it, oldItems) { ShopItem *const item = *it; if (item == nullptr) continue; const Item *const cartItem = inv->findItem(item->getId(), item->getColor()); if (cartItem == nullptr) continue; item->setInvIndex(cartItem->getInvIndex()); const int amount = cartItem->getQuantity(); if (amount == 0) continue; if (item->getQuantity() > amount) item->setQuantity(amount); items.push_back(item); if (static_cast(items.size()) >= mSellShopSize) break; } if (!items.empty()) vendingHandler->createShop(mSellShopName, true, items); } } } else if (eventId == "rename") { EditDialog *const dialog = CREATEWIDGETR(EditDialog, // TRANSLATORS: shop rename dialog title _("Please enter new shop name"), mSellShopName, "OK", 300, nullptr, Modal_true); shopRenameListener.setDialog(dialog); dialog->addActionListener(&shopRenameListener); } if (mSelectedItem < 1) return; const Inventory *const inv = mHaveVending && !isBuySelected ? PlayerInfo::getCartInventory() : PlayerInfo::getInventory(); if (inv == nullptr) return; // +++ need support for colors Item *const item = inv->findItem(mSelectedItem, ItemColor_zero); if (item != nullptr) { if (eventId == "add") { if (isBuySelected) { ItemAmountWindow::showWindow(ItemAmountWindowUsage::ShopBuyAdd, this, item, sumAmount(item), 0); } else { ItemAmountWindow::showWindow( ItemAmountWindowUsage::ShopSellAdd, this, item, sumAmount(item), 0); } } } } void ShopWindow::valueChanged(const SelectionEvent &event A_UNUSED) { updateButtonsAndLabels(); } void ShopWindow::updateButtonsAndLabels() { bool allowDel(false); bool allowAdd(false); if (isBuySelected) { allowAdd = !mEnableBuyingStore; allowDel = !mEnableBuyingStore && mBuyShopItemList->getSelected() != -1 && mBuyShopItems->getNumberOfElements() > 0; if (mPublishButton != nullptr) { if (mEnableBuyingStore) { // TRANSLATORS: unpublish shop button mPublishButton->setCaption(_("Unpublish")); } else { // TRANSLATORS: publish shop button mPublishButton->setCaption(_("Publish")); } mPublishButton->adjustSize(); if (mBuyShopSize > 0) mPublishButton->setEnabled(true); else mPublishButton->setEnabled(false); } } else { const bool sellNotEmpty = mSellShopItems->getNumberOfElements() > 0; allowAdd = !mEnableVending && mSelectedItem != -1; allowDel = !mEnableVending && mSellShopItemList->getSelected() != -1 && sellNotEmpty; if (mPublishButton != nullptr) { if (mEnableVending) { // TRANSLATORS: unpublish shop button mPublishButton->setCaption(_("Unpublish")); } else { // TRANSLATORS: publish shop button mPublishButton->setCaption(_("Publish")); } mPublishButton->adjustSize(); if (sellNotEmpty && mSellShopSize > 0 && (localPlayer != nullptr) && localPlayer->getHaveCart()) { mPublishButton->setEnabled(true); } else { mPublishButton->setEnabled(false); } } } mAddButton->setEnabled(allowAdd); mDeleteButton->setEnabled(allowDel); if (mRenameButton != nullptr) mRenameButton->setEnabled(!mEnableVending); } void ShopWindow::setVisible(Visible visible) { Window::setVisible(visible); } void ShopWindow::addBuyItem(const Item *const item, const int amount, const int price) { if (item == nullptr) return; const bool emp = isShopEmpty(); mBuyShopItems->addItemNoDup(item->getId(), item->getType(), item->getColor(), amount, price); if (emp && (localPlayer != nullptr)) localPlayer->updateStatus(); updateButtonsAndLabels(); } void ShopWindow::addSellItem(const Item *const item, const int amount, const int price) { if (item == nullptr) return; const bool emp = isShopEmpty(); mSellShopItems->addItemNoDup(item->getId(), item->getType(), item->getColor(), amount, price); if (emp && (localPlayer != nullptr)) localPlayer->updateStatus(); updateButtonsAndLabels(); } void ShopWindow::loadList() { std::ifstream shopFile; struct stat statbuf; mBuyShopItems->clear(); mSellShopItems->clear(); const std::string shopListName = settings.serverConfigDir + "/shoplist.txt"; if (stat(shopListName.c_str(), &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { shopFile.open(shopListName.c_str(), std::ios::in); if (!shopFile.is_open()) { reportAlways("Error opening file for reading: %s", shopListName.c_str()) shopFile.close(); return; } char line[101]; while (shopFile.getline(line, 100)) { std::string buf; const std::string str = line; if (!str.empty()) { STD_VECTOR tokens; std::stringstream ss(str); while (ss >> buf) tokens.push_back(atoi(buf.c_str())); if (tokens.size() == 5 && (tokens[0] != 0)) { // +++ need impliment colors? if ((tokens[1] != 0) && (tokens[2] != 0)) { mBuyShopItems->addItem( tokens[0], ItemType::Unknown, ItemColor_one, tokens[1], tokens[2]); } if ((tokens[3] != 0) && (tokens[4] != 0)) { mSellShopItems->addItem( tokens[0], ItemType::Unknown, ItemColor_one, tokens[3], tokens[4]); } } } } shopFile.close(); } } void ShopWindow::saveList() const { std::ofstream shopFile; const std::string shopListName = settings.serverConfigDir + "/shoplist.txt"; std::map mapItems; shopFile.open(shopListName.c_str(), std::ios::binary); if (!shopFile.is_open()) { reportAlways("Error opening file writing: %s", shopListName.c_str()) return; } STD_VECTOR items = mBuyShopItems->items(); FOR_EACH (STD_VECTOR::const_iterator, it, items) { ShopItem *const item = *(it); if (item != nullptr) mapItems[item->getId()] = item; } items = mSellShopItems->items(); FOR_EACH (STD_VECTOR::const_iterator, it, items) { if ((*it) == nullptr) continue; const ShopItem *const sellItem = *(it); const ShopItem *const buyItem = mapItems[sellItem->getId()]; shopFile << sellItem->getId(); if (buyItem != nullptr) { shopFile << strprintf(" %d %d ", buyItem->getQuantity(), buyItem->getPrice()); mapItems.erase(sellItem->getId()); } else { shopFile << " 0 0 "; } shopFile << strprintf("%d %d", sellItem->getQuantity(), sellItem->getPrice()) << std::endl; } for (std::map::const_iterator mapIt = mapItems.begin(), mapIt_fend = mapItems.end(); mapIt != mapIt_fend; ++mapIt) { const ShopItem *const buyItem = (*mapIt).second; if (buyItem != nullptr) { shopFile << buyItem->getId(); shopFile << strprintf(" %d %d ", buyItem->getQuantity(), buyItem->getPrice()); shopFile << "0 0" << std::endl; } } shopFile.close(); } #ifdef TMWA_SUPPORT void ShopWindow::announce(ShopItems *const list, const int mode) { if (list == nullptr) return; std::string data; if (mode == BUY) data.append("Buy "); else data.append("Sell "); if (mAnnonceTime != 0 && (mAnnonceTime + (2 * 60) > cur_time || mAnnonceTime > cur_time)) { return; } mAnnonceTime = cur_time; if (mAnnounceButton != nullptr) mAnnounceButton->setEnabled(false); STD_VECTOR items = list->items(); FOR_EACH (STD_VECTOR::const_iterator, it, items) { const ShopItem *const item = *(it); if (item->getQuantity() > 1) { if (mAnnounceLinks->isSelected()) { data.append(strprintf("[@@%d|%s@@] (%dGP) %d, ", item->getId(), item->getInfo().getName().c_str(), item->getPrice(), item->getQuantity())); } else { data.append(strprintf("%s (%dGP) %d, ", item->getInfo().getName().c_str(), item->getPrice(), item->getQuantity())); } } else { if (mAnnounceLinks->isSelected()) { data.append(strprintf("[@@%d|%s@@] (%dGP), ", item->getId(), item->getInfo().getName().c_str(), item->getPrice())); } else { data.append(strprintf("%s (%dGP), ", item->getInfo().getName().c_str(), item->getPrice())); } } } chatHandler->channelMessage(TRADE_CHANNEL, data); } void ShopWindow::startTrade() { if (actorManager == nullptr || tradeWindow == nullptr) { return; } const Being *const being = actorManager->findBeingByName( mTradeNick, ActorType::Player); tradeWindow->clear(); if (mTradeMoney != 0) { tradeWindow->addAutoMoney(mTradeNick, mTradeMoney); } else { tradeWindow->addAutoItem(mTradeNick, mTradeItem, mTradeItem->getQuantity()); } tradeHandler->request(being); tradePartnerName = mTradeNick; mTradeNick.clear(); } void ShopWindow::giveList(const std::string &nick, const int mode) { if (!checkFloodCounter(mLastRequestTimeList)) return; std::string data("\302\202"); ShopItems *list; if (mode == BUY) { list = mBuyShopItems; data.append("S1"); } else { list = mSellShopItems; data.append("B1"); } if (list == nullptr) return; const Inventory *const inv = PlayerInfo::getInventory(); if (inv == nullptr) return; STD_VECTOR items = list->items(); FOR_EACH (STD_VECTOR::const_iterator, it, items) { const ShopItem *const item = *(it); if (item == nullptr) continue; if (mode == SELL) { const Item *const item2 = inv->findItem(item->getId(), ItemColor_zero); if (item2 != nullptr) { int amount = item->getQuantity(); if (item2->getQuantity() < amount) amount = item2->getQuantity(); if (amount != 0) { data.append(strprintf("%s%s%s", encodeStr(item->getId(), 2).c_str(), encodeStr(item->getPrice(), 4).c_str(), encodeStr(amount, 3).c_str())); } } } else { int amount = item->getQuantity(); if (item->getPrice() * amount > PlayerInfo::getAttribute( Attributes::MONEY)) { amount = PlayerInfo::getAttribute(Attributes::MONEY) / item->getPrice(); } if (amount > 0) { data.append(strprintf("%s%s%s", encodeStr(item->getId(), 2).c_str(), encodeStr(item->getPrice(), 4).c_str(), encodeStr(amount, 3).c_str())); } } } sendMessage(nick, data, true); } void ShopWindow::sendMessage(const std::string &nick, std::string data, const bool random) { if (chatWindow == nullptr) return; if (random) { mRandCounter ++; if (mRandCounter > 200) mRandCounter = 0; data.append(encodeStr(mRandCounter, 2)); } if (config.getBoolValue("hideShopMessages")) chatHandler->privateMessage(nick, data); else chatWindow->addWhisper(nick, data, ChatMsgType::BY_PLAYER); } void ShopWindow::showList(const std::string &nick, std::string data) { const Inventory *const inv = PlayerInfo::getInventory(); if (inv == nullptr) return; BuyDialog *buyDialog = nullptr; SellDialog *sellDialog = nullptr; if (data.find("B1") == 0) { data = data.substr(2); CREATEWIDGETV(buyDialog, BuyDialog, nick, DEFAULT_CURRENCY); } else if (data.find("S1") == 0) { data = data.substr(2); CREATEWIDGETV(sellDialog, ShopSellDialog, nick); } else { return; } if (buyDialog != nullptr) buyDialog->setMoney(PlayerInfo::getAttribute(Attributes::MONEY)); if (sellDialog != nullptr) sellDialog->setMoney(PlayerInfo::getAttribute(Attributes::MONEY)); for (size_t f = 0; f < data.length(); f += 9) { if (f + 9 > data.length()) break; const int id = decodeStr(data.substr(f, 2)); const int price = decodeStr(data.substr(f + 2, 4)); int amount = decodeStr(data.substr(f + 6, 3)); if (buyDialog != nullptr && amount > 0) { buyDialog->addItem(id, ItemType::Unknown, ItemColor_one, amount, price); } if (sellDialog != nullptr) { const Item *const item = inv->findItem(id, ItemColor_zero); if (item != nullptr) { if (item->getQuantity() < amount) amount = item->getQuantity(); } else { amount = 0; } ShopItem *const shopItem = sellDialog->addItem(id, ItemType::Unknown, ItemColor_one, amount, price); if (shopItem != nullptr && amount <= 0) shopItem->setDisabled(true); } } if (buyDialog != nullptr) buyDialog->sort(); } void ShopWindow::processRequest(const std::string &nick, std::string data, const int mode) { if (localPlayer == nullptr || !mTradeNick.empty() || PlayerInfo::isTrading() == Trading_true || actorManager == nullptr || actorManager->findBeingByName(nick, ActorType::Player) == nullptr) { return; } const Inventory *const inv = PlayerInfo::getInventory(); if (inv == nullptr) return; const size_t idx = data.find(' '); if (idx == std::string::npos) return; if (!checkFloodCounter(mLastRequestTimeItem)) return; if (!mTradeNick.empty()) { sendMessage(nick, // TRANSLATORS: error buy/sell shop request _("error: player busy") + std::string(" "), true); return; } data = data.substr(idx + 1); std::string part1; std::string part2; std::string part3; std::stringstream ss(data); int id; int price; int amount; if (!(ss >> part1)) return; if (!(ss >> part2)) return; if (!(ss >> part3)) return; id = atoi(part1.c_str()); price = atoi(part2.c_str()); amount = atoi(part3.c_str()); delete mTradeItem; // +++ need impliment colors? mTradeItem = new ShopItem(-1, id, ItemType::Unknown, ItemColor_one, amount, price, DEFAULT_CURRENCY); if (mode == BUY) { // +++ need support for colors const Item *const item2 = inv->findItem(mTradeItem->getId(), ItemColor_zero); if (item2 == nullptr || item2->getQuantity() < amount || !findShopItem(mTradeItem, SELL)) { sendMessage(nick, // TRANSLATORS: error buy/sell shop request _("error: Can't sell this item") + std::string(" "), true); return; } mTradeMoney = 0; } else { if (!findShopItem(mTradeItem, BUY)) { sendMessage(nick, // TRANSLATORS: error buy/sell shop request _("error: Can't buy this item") + std::string(" "), true); return; } mTradeMoney = mTradeItem->getPrice() * mTradeItem->getQuantity(); } mTradeNick = nick; if (config.getBoolValue("autoShop")) { soundManager.playGuiSound(SOUND_TRADE); startTrade(); } else { std::string msg; if (mode == BUY) { // TRANSLATORS: buy shop request (nick, item) msg = strprintf(_("%s wants to buy %s do you accept?"), nick.c_str(), mTradeItem->getInfo().getName().c_str()); } else { // TRANSLATORS: sell shop request (nick, item) msg = strprintf(_("%s wants to sell %s do you accept?"), nick.c_str(), mTradeItem->getInfo().getName().c_str()); } ConfirmDialog *const confirmDlg = CREATEWIDGETR(ConfirmDialog, // TRANSLATORS: shop window dialog _("Request for Trade"), msg, SOUND_REQUEST, true, Modal_false, nullptr); confirmDlg->addActionListener(this); } } void ShopWindow::updateTimes() { BLOCK_START("ShopWindow::updateTimes") if (mAnnounceButton == nullptr) { BLOCK_END("ShopWindow::updateTimes") return; } if (mAnnonceTime + (2 * 60) < cur_time || mAnnonceTime > cur_time) { mAnnounceButton->setEnabled(true); } BLOCK_END("ShopWindow::updateTimes") } bool ShopWindow::checkFloodCounter(time_t &counterTime) { if (counterTime == 0 || counterTime > cur_time) counterTime = cur_time; else if (counterTime + 10 > cur_time) return false; else counterTime = cur_time; return true; } bool ShopWindow::findShopItem(const ShopItem *const shopItem, const int mode) const { if (shopItem == nullptr) return false; STD_VECTOR items; if (mode == SELL) items = mSellShopItems->items(); else items = mBuyShopItems->items(); FOR_EACH (STD_VECTOR::const_iterator, it, items) { const ShopItem *const item = *(it); if (item == nullptr) continue; if (item->getId() == shopItem->getId() && item->getPrice() == shopItem->getPrice() && item->getQuantity() >= shopItem->getQuantity()) { return true; } } return false; } #endif // TMWA_SUPPORT int ShopWindow::sumAmount(const Item *const shopItem) { if ((localPlayer == nullptr) || (shopItem == nullptr)) return 0; const Inventory *const inv = PlayerInfo::getInventory(); if (inv == nullptr) return 0; int sum = 0; for (unsigned f = 0; f < inv->getSize(); f ++) { const Item *const item = inv->getItem(f); if ((item != nullptr) && item->getId() == shopItem->getId()) sum += item->getQuantity(); } return sum; } bool ShopWindow::isShopEmpty() const { if (mBuyShopItems->empty() && mSellShopItems->empty()) return true; return false; } void ShopWindow::updateSelection() { if (isBuySelected) mCurrentShopItemList = mBuyShopItemList; else mCurrentShopItemList = mSellShopItemList; mScrollArea->setContent(mCurrentShopItemList); updateButtonsAndLabels(); } void ShopWindow::updateShopName() { if (mSellShopName.empty()) { // TRANSLATORS: shop window name setCaption(_("Personal Shop")); } else { // TRANSLATORS: shop window name setCaption(strprintf(_("Personal Shop - %s"), mSellShopName.c_str())); } } void ShopWindow::setShopName(const std::string &name) { mSellShopName = name; serverConfig.setValue("sellShopName", mSellShopName); updateShopName(); } void ShopWindow::vendingSlotsChanged(const int slots) { mSellShopSize = slots; updateButtonsAndLabels(); } void ShopWindow::vendingEnabled(const bool b) { mEnableVending = b; localPlayer->enableShop(b); if (!b) mSellShopSize = 0; updateButtonsAndLabels(); } void ShopWindow::buyingStoreSlotsChanged(const int slots) { mBuyShopSize = slots; updateButtonsAndLabels(); } void ShopWindow::buyingStoreEnabled(const bool b) { mEnableBuyingStore = b; localPlayer->enableShop(b); if (!b) mBuyShopSize = 0; updateButtonsAndLabels(); }