ManaPlus
shopwindow.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2004-2009 The Mana World Development Team
4  * Copyright (C) 2009-2010 The Mana Developers
5  * Copyright (C) 2011-2018 The ManaPlus Developers
6  *
7  * This file is part of The ManaPlus Client.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "gui/windows/shopwindow.h"
24 
26 
27 #ifdef TMWA_SUPPORT
28 #include "gui/windows/buydialog.h"
29 #include "gui/windows/chatwindow.h"
33 
34 #include "const/sound.h"
35 
36 #include "const/gui/chat.h"
37 #endif // TMWA_SUPPORT
38 
39 #include "enums/gui/layouttype.h"
40 
41 #include "gui/windows/editdialog.h"
42 
45 
46 #include "gui/models/shopitems.h"
47 
48 #include "gui/widgets/button.h"
49 #include "gui/widgets/checkbox.h"
52 #include "gui/widgets/layout.h"
53 #include "gui/widgets/scrollarea.h"
55 #include "gui/widgets/tabstrip.h"
56 
58 
59 #ifdef TMWA_SUPPORT
60 #include "actormanager.h"
61 #include "soundmanager.h"
62 #endif // TMWA_SUPPORT
63 #include "configuration.h"
64 #include "settings.h"
65 
66 #include "being/localplayer.h"
67 #include "being/playerinfo.h"
68 
69 #ifdef TMWA_SUPPORT
70 #include "being/playerrelations.h"
71 #include "net/chathandler.h"
72 #endif // TMWA_SUPPORT
73 #include "net/buyingstorehandler.h"
74 #include "net/vendinghandler.h"
75 #include "net/net.h"
76 #ifdef TMWA_SUPPORT
77 #include "net/tradehandler.h"
78 #endif // TMWA_SUPPORT
79 
80 #include "utils/checkutils.h"
81 #include "utils/delete2.h"
82 #include "utils/foreach.h"
83 #include "utils/gettext.h"
84 
85 #ifdef TMWA_SUPPORT
86 #include "resources/iteminfo.h"
87 #endif // TMWA_SUPPORT
88 
90 
92 
93 #include <sys/stat.h>
94 
95 #include <sstream>
96 
97 #include "debug.h"
98 
100 extern std::string tradePartnerName;
102 
104  // TRANSLATORS: shop window name
105  Window(_("Personal Shop"), Modal_false, nullptr, "shop.xml"),
110  ActionListener(),
112  // TRANSLATORS: shop window button
113  mCloseButton(new Button(this, _("Close"), "close", this)),
114  mBuyShopItems(new ShopItems(false, DEFAULT_CURRENCY)),
115  mSellShopItems(new ShopItems(false, DEFAULT_CURRENCY)),
116  mTradeItem(nullptr),
117  mBuyShopItemList(CREATEWIDGETR(ShopListBox,
118  this, mBuyShopItems, mBuyShopItems, ShopListBoxType::BuyShop)),
119  mSellShopItemList(CREATEWIDGETR(ShopListBox,
120  this, mSellShopItems, mSellShopItems, ShopListBoxType::SellShop)),
121  mCurrentShopItemList(nullptr),
122  mScrollArea(new ScrollArea(this, mBuyShopItemList,
123  fromBool(getOptionBool("showbuybackground", false), Opaque),
124  "shop_buy_background.xml")),
125  // TRANSLATORS: shop window label
126  mAddButton(new Button(this, _("Add"), "add", this)),
127  // TRANSLATORS: shop window label
128  mDeleteButton(new Button(this, _("Delete"), "delete", this)),
129  mAnnounceButton(nullptr),
130  mPublishButton(nullptr),
131  mRenameButton(nullptr),
132  mAnnounceLinks(nullptr),
133  mTabs(nullptr),
134  mAcceptPlayer(),
135  mTradeNick(),
136  mSellShopName(serverConfig.getStringValue("sellShopName")),
137  mSelectedItem(-1),
138  mAnnonceTime(0),
139  mLastRequestTimeList(0),
140  mLastRequestTimeItem(0),
141  mRandCounter(0),
142  mTradeMoney(0),
143  mSellShopSize(0),
144  mBuyShopSize(0),
145  isBuySelected(true),
146  mHaveVending(Net::getNetworkType() != ServerType::TMWATHENA),
147  mEnableBuyingStore(false),
148  mEnableVending(false)
149 {
150  setWindowName("Personal Shop");
151  setResizable(true);
152  setCloseButton(true);
153  setStickyButtonLock(true);
154  setMinWidth(300);
155  setMinHeight(220);
156  if (mainGraphics->mWidth > 600)
157  setDefaultSize(500, 300, ImagePosition::CENTER, 0, 0);
158  else
159  setDefaultSize(380, 300, ImagePosition::CENTER, 0, 0);
160 
161  if (setupWindow != nullptr)
163 
164  const int size = config.getIntValue("fontSize")
165  + getOption("tabHeightAdjust", 16);
166  mTabs = new TabStrip(this, "shop", size, 0);
167  mTabs->addActionListener(this);
168  mTabs->setActionEventId("tab_");
169  // TRANSLATORS: shop window tab name
170  mTabs->addButton(_("Buy"), "buy", true);
171  // TRANSLATORS: shop window tab name
172  mTabs->addButton(_("Sell"), "sell", false);
173  mTabs->setSelectable(false);
174  mScrollArea->setSelectable(false);
175 
176  loadList();
177 
180 
182 
185 
186  ContainerPlacer placer(nullptr, nullptr);
187  placer = getPlacer(0, 0);
188 
189  placer(0, 0, mTabs, 8, 1).setPadding(3);
190 
191  if (mHaveVending)
192  {
193  // TRANSLATORS: shop window button
194  mPublishButton = new Button(this, _("Publish"), "publish", this);
195  // TRANSLATORS: shop window button
196  mRenameButton = new Button(this, _("Rename"), "rename", this);
197  placer(2, 6, mPublishButton, 1, 1);
198  placer(3, 6, mRenameButton, 1, 1);
199  }
200  else
201  {
202  // TRANSLATORS: shop window button
203  mAnnounceButton = new Button(this, _("Announce"), "announce", this);
204  // TRANSLATORS: shop window checkbox
205  mAnnounceLinks = new CheckBox(this, _("Show links in announce"), false,
206  this, "link announce");
207 
208  placer(2, 6, mAnnounceButton, 1, 1);
209  placer(0, 7, mAnnounceLinks, 7, 1);
210  }
211 
212  placer(0, 1, mScrollArea, 8, 5).setPadding(3);
213  placer(0, 6, mAddButton, 1, 1);
214  placer(1, 6, mDeleteButton, 1, 1);
215  placer(7, 6, mCloseButton, 1, 1);
216 
217  Layout &layout = getLayout();
218  layout.setRowHeight(0, LayoutType::SET);
219 
220  center();
221  loadWindowState();
222  updateShopName();
223  instances.push_back(this);
224 }
225 
227 {
230  enableVisibleSound(true);
231  updateSelection();
232 }
233 
235 {
236  saveList();
237 
243 
244  instances.remove(this);
245 }
246 
247 void ShopWindow::action(const ActionEvent &event)
248 {
249  const std::string &eventId = event.getId();
250  if (eventId == "close")
251  {
252  close();
253  return;
254  }
255 #ifdef TMWA_SUPPORT
256  else if (eventId == "yes")
257  {
258  startTrade();
259  }
260  else if (eventId == "no")
261  {
262  mTradeNick.clear();
263  }
264  else if (eventId == "ignore")
265  {
267  mTradeNick.clear();
268  }
269  else if (eventId == "announce")
270  {
271  if (isBuySelected)
272  {
275  }
276  else if (mSellShopItems->getNumberOfElements() > 0)
277  {
279  }
280  }
281 #endif // TMWA_SUPPORT
282  else if (eventId == "delete")
283  {
284  if (isBuySelected)
285  {
286  if (mBuyShopItemList != nullptr &&
288  {
290  if (isShopEmpty() && (localPlayer != nullptr))
292  }
293  }
294  else if ((mSellShopItemList != nullptr)
295  && mSellShopItemList->getSelected() >= 0)
296  {
298  if (isShopEmpty() && (localPlayer != nullptr))
300  }
301  }
302  else if (eventId == "tab_buy")
303  {
304  isBuySelected = true;
305  updateSelection();
306  }
307  else if (eventId == "tab_sell")
308  {
309  isBuySelected = false;
310  updateSelection();
311  }
312  else if (eventId == "publish")
313  {
314  if (isBuySelected)
315  {
316  if (mEnableBuyingStore)
317  {
320  }
321  else
322  {
323  STD_VECTOR<ShopItem*> &items = mBuyShopItems->items();
324  if (!items.empty())
325  {
328  true,
329  items);
330  }
331  }
332  }
333  else
334  {
335  if (mEnableVending)
336  {
339  }
340  else
341  {
342  STD_VECTOR<ShopItem*> &oldItems = mSellShopItems->items();
343  STD_VECTOR<ShopItem*> items;
344  const Inventory *const inv = PlayerInfo::getCartInventory();
345  if (inv == nullptr)
346  return;
347  FOR_EACH (STD_VECTOR<ShopItem*>::iterator, it, oldItems)
348  {
349  ShopItem *const item = *it;
350  if (item == nullptr)
351  continue;
352  const Item *const cartItem = inv->findItem(item->getId(),
353  item->getColor());
354  if (cartItem == nullptr)
355  continue;
356  item->setInvIndex(cartItem->getInvIndex());
357  const int amount = cartItem->getQuantity();
358  if (amount == 0)
359  continue;
360  if (item->getQuantity() > amount)
361  item->setQuantity(amount);
362  items.push_back(item);
363  if (static_cast<signed int>(items.size()) >= mSellShopSize)
364  break;
365  }
366  if (!items.empty())
367  vendingHandler->createShop(mSellShopName, true, items);
368  }
369  }
370  }
371  else if (eventId == "rename")
372  {
373  EditDialog *const dialog = CREATEWIDGETR(EditDialog,
374  // TRANSLATORS: shop rename dialog title
375  _("Please enter new shop name"),
377  "OK",
378  300,
379  nullptr,
380  Modal_true);
383  }
384 
385  if (mSelectedItem < 1)
386  return;
387 
388  const Inventory *const inv = mHaveVending && !isBuySelected
390  if (inv == nullptr)
391  return;
392 
393  // +++ need support for colors
395  if (item != nullptr)
396  {
397  if (eventId == "add")
398  {
399  if (isBuySelected)
400  {
402  this,
403  item,
404  sumAmount(item),
405  0);
406  }
407  else
408  {
411  this,
412  item,
413  sumAmount(item),
414  0);
415  }
416  }
417  }
418 }
419 
421 {
423 }
424 
426 {
427  bool allowDel(false);
428  bool allowAdd(false);
429  const bool sellNotEmpty = mSellShopItems->getNumberOfElements() > 0;
430  if (isBuySelected)
431  {
432  allowAdd = !mEnableBuyingStore;
433  allowDel = !mEnableBuyingStore
434  && mBuyShopItemList->getSelected() != -1
436  if (mPublishButton != nullptr)
437  {
438  if (mEnableBuyingStore)
439  {
440  // TRANSLATORS: unpublish shop button
441  mPublishButton->setCaption(_("Unpublish"));
442  }
443  else
444  {
445  // TRANSLATORS: publish shop button
446  mPublishButton->setCaption(_("Publish"));
447  }
449  if (mBuyShopSize > 0)
450  mPublishButton->setEnabled(true);
451  else
452  mPublishButton->setEnabled(false);
453  }
454  }
455  else
456  {
457  allowAdd = !mEnableVending && mSelectedItem != -1;
458  allowDel = !mEnableVending
459  && mSellShopItemList->getSelected() != -1
460  && sellNotEmpty;
461  if (mPublishButton != nullptr)
462  {
463  if (mEnableVending)
464  {
465  // TRANSLATORS: unpublish shop button
466  mPublishButton->setCaption(_("Unpublish"));
467  }
468  else
469  {
470  // TRANSLATORS: publish shop button
471  mPublishButton->setCaption(_("Publish"));
472  }
474  if (sellNotEmpty
475  && mSellShopSize > 0
476  && (localPlayer != nullptr)
477  && localPlayer->getHaveCart())
478  {
479  mPublishButton->setEnabled(true);
480  }
481  else
482  {
483  mPublishButton->setEnabled(false);
484  }
485  }
486  }
487  mAddButton->setEnabled(allowAdd);
488  mDeleteButton->setEnabled(allowDel);
489  if (mRenameButton != nullptr)
491 }
492 
494 {
495  Window::setVisible(visible);
496 }
497 
498 void ShopWindow::addBuyItem(const Item *const item, const int amount,
499  const int price)
500 {
501  if (item == nullptr)
502  return;
503  const bool emp = isShopEmpty();
505  item->getType(),
506  item->getColor(),
507  amount,
508  price);
509  if (emp && (localPlayer != nullptr))
511 
513 }
514 
515 void ShopWindow::addSellItem(const Item *const item, const int amount,
516  const int price)
517 {
518  if (item == nullptr)
519  return;
520  const bool emp = isShopEmpty();
522  item->getType(),
523  item->getColor(),
524  amount,
525  price);
526  if (emp && (localPlayer != nullptr))
528 
530 }
531 
533 {
534  std::ifstream shopFile;
535  struct stat statbuf;
536 
537  mBuyShopItems->clear();
539 
540  const std::string shopListName = settings.serverConfigDir
541  + "/shoplist.txt";
542 
543  if (stat(shopListName.c_str(), &statbuf) == 0 &&
544  S_ISREG(statbuf.st_mode))
545  {
546  shopFile.open(shopListName.c_str(), std::ios::in);
547  if (!shopFile.is_open())
548  {
549  reportAlways("Error opening file for reading: %s",
550  shopListName.c_str());
551  shopFile.close();
552  return;
553  }
554  char line[101];
555  while (shopFile.getline(line, 100))
556  {
557  std::string buf;
558  const std::string str = line;
559  if (!str.empty())
560  {
561  STD_VECTOR<int> tokens;
562  std::stringstream ss(str);
563 
564  while (ss >> buf)
565  tokens.push_back(atoi(buf.c_str()));
566 
567  if (tokens.size() == 5 && (tokens[0] != 0))
568  {
569  // +++ need impliment colors?
570  if ((tokens[1] != 0) && (tokens[2] != 0))
571  {
573  tokens[0],
576  tokens[1],
577  tokens[2]);
578  }
579  if ((tokens[3] != 0) && (tokens[4] != 0))
580  {
582  tokens[0],
585  tokens[3],
586  tokens[4]);
587  }
588  }
589  }
590  }
591  shopFile.close();
592  }
593 }
594 
596 {
597  std::ofstream shopFile;
598  const std::string shopListName = settings.serverConfigDir
599  + "/shoplist.txt";
600  std::map<int, ShopItem*> mapItems;
601 
602  shopFile.open(shopListName.c_str(), std::ios::binary);
603  if (!shopFile.is_open())
604  {
605  reportAlways("Error opening file writing: %s",
606  shopListName.c_str());
607  return;
608  }
609 
610  STD_VECTOR<ShopItem*> items = mBuyShopItems->items();
611  FOR_EACH (STD_VECTOR<ShopItem*>::const_iterator, it, items)
612  {
613  ShopItem *const item = *(it);
614  if (item != nullptr)
615  mapItems[item->getId()] = item;
616  }
617 
618  items = mSellShopItems->items();
619  FOR_EACH (STD_VECTOR<ShopItem*>::const_iterator, it, items)
620  {
621  if ((*it) == nullptr)
622  continue;
623  const ShopItem *const sellItem = *(it);
624  const ShopItem *const buyItem = mapItems[sellItem->getId()];
625 
626  shopFile << sellItem->getId();
627  if (buyItem != nullptr)
628  {
629  shopFile << strprintf(" %d %d ", buyItem->getQuantity(),
630  buyItem->getPrice());
631  mapItems.erase(sellItem->getId());
632  }
633  else
634  {
635  shopFile << " 0 0 ";
636  }
637 
638  shopFile << strprintf("%d %d", sellItem->getQuantity(),
639  sellItem->getPrice()) << std::endl;
640  }
641 
642  for (std::map<int, ShopItem*>::const_iterator mapIt = mapItems.begin(),
643  mapIt_fend = mapItems.end();
644  mapIt != mapIt_fend;
645  ++mapIt)
646  {
647  const ShopItem *const buyItem = (*mapIt).second;
648  if (buyItem != nullptr)
649  {
650  shopFile << buyItem->getId();
651  shopFile << strprintf(" %d %d ", buyItem->getQuantity(),
652  buyItem->getPrice());
653  shopFile << "0 0" << std::endl;
654  }
655  }
656 
657  shopFile.close();
658 }
659 
660 #ifdef TMWA_SUPPORT
661 void ShopWindow::announce(ShopItems *const list, const int mode)
662 {
663  if (list == nullptr)
664  return;
665 
666  std::string data;
667  if (mode == BUY)
668  data.append("Buy ");
669  else
670  data.append("Sell ");
671 
672  if (mAnnonceTime != 0 &&
673  (mAnnonceTime + (2 * 60) > cur_time || mAnnonceTime > cur_time))
674  {
675  return;
676  }
677 
679  if (mAnnounceButton != nullptr)
680  mAnnounceButton->setEnabled(false);
681 
682  STD_VECTOR<ShopItem*> items = list->items();
683 
684  FOR_EACH (STD_VECTOR<ShopItem*>::const_iterator, it, items)
685  {
686  const ShopItem *const item = *(it);
687  if (item->getQuantity() > 1)
688  {
689  if (mAnnounceLinks->isSelected())
690  {
691  data.append(strprintf("[@@%d|%[email protected]@] (%dGP) %d, ", item->getId(),
692  item->getInfo().getName().c_str(),
693  item->getPrice(), item->getQuantity()));
694  }
695  else
696  {
697  data.append(strprintf("%s (%dGP) %d, ",
698  item->getInfo().getName().c_str(),
699  item->getPrice(), item->getQuantity()));
700  }
701  }
702  else
703  {
704  if (mAnnounceLinks->isSelected())
705  {
706  data.append(strprintf("[@@%d|%[email protected]@] (%dGP), ", item->getId(),
707  item->getInfo().getName().c_str(), item->getPrice()));
708  }
709  else
710  {
711  data.append(strprintf("%s (%dGP), ",
712  item->getInfo().getName().c_str(), item->getPrice()));
713  }
714  }
715  }
716 
718 }
719 
721 {
722  if (actorManager == nullptr ||
723  tradeWindow == nullptr)
724  {
725  return;
726  }
727 
728  const Being *const being = actorManager->findBeingByName(
730  tradeWindow->clear();
731  if (mTradeMoney != 0)
732  {
734  }
735  else
736  {
739  }
740  tradeHandler->request(being);
742  mTradeNick.clear();
743 }
744 
745 void ShopWindow::giveList(const std::string &nick, const int mode)
746 {
748  return;
749 
750  std::string data("\302\202");
751 
752  ShopItems *list;
753  if (mode == BUY)
754  {
755  list = mBuyShopItems;
756  data.append("S1");
757  }
758  else
759  {
760  list = mSellShopItems;
761  data.append("B1");
762  }
763  if (list == nullptr)
764  return;
765 
766  const Inventory *const inv = PlayerInfo::getInventory();
767  if (inv == nullptr)
768  return;
769 
770  STD_VECTOR<ShopItem*> items = list->items();
771 
772  FOR_EACH (STD_VECTOR<ShopItem*>::const_iterator, it, items)
773  {
774  const ShopItem *const item = *(it);
775  if (item == nullptr)
776  continue;
777 
778  if (mode == SELL)
779  {
780  const Item *const item2 = inv->findItem(item->getId(),
782  if (item2 != nullptr)
783  {
784  int amount = item->getQuantity();
785  if (item2->getQuantity() < amount)
786  amount = item2->getQuantity();
787 
788  if (amount != 0)
789  {
790  data.append(strprintf("%s%s%s",
791  encodeStr(item->getId(), 2).c_str(),
792  encodeStr(item->getPrice(), 4).c_str(),
793  encodeStr(amount, 3).c_str()));
794  }
795  }
796  }
797  else
798  {
799  int amount = item->getQuantity();
800  if (item->getPrice() * amount > PlayerInfo::getAttribute(
802  {
804  / item->getPrice();
805  }
806 
807  if (amount > 0)
808  {
809  data.append(strprintf("%s%s%s",
810  encodeStr(item->getId(), 2).c_str(),
811  encodeStr(item->getPrice(), 4).c_str(),
812  encodeStr(amount, 3).c_str()));
813  }
814  }
815  }
816  sendMessage(nick, data, true);
817 }
818 
819 void ShopWindow::sendMessage(const std::string &nick,
820  std::string data,
821  const bool random)
822 {
823  if (chatWindow == nullptr)
824  return;
825 
826  if (random)
827  {
828  mRandCounter ++;
829  if (mRandCounter > 200)
830  mRandCounter = 0;
831  data.append(encodeStr(mRandCounter, 2));
832  }
833 
834  if (config.getBoolValue("hideShopMessages"))
835  chatHandler->privateMessage(nick, data);
836  else
838 }
839 
840 void ShopWindow::showList(const std::string &nick, std::string data)
841 {
842  const Inventory *const inv = PlayerInfo::getInventory();
843  if (inv == nullptr)
844  return;
845 
846  BuyDialog *buyDialog = nullptr;
847  SellDialog *sellDialog = nullptr;
848  if (data.find("B1") == 0)
849  {
850  data = data.substr(2);
851  CREATEWIDGETV(buyDialog, BuyDialog, nick, DEFAULT_CURRENCY);
852  }
853  else if (data.find("S1") == 0)
854  {
855  data = data.substr(2);
856  CREATEWIDGETV(sellDialog, ShopSellDialog, nick);
857  }
858  else
859  {
860  return;
861  }
862 
863  if (buyDialog != nullptr)
865  if (sellDialog != nullptr)
867 
868  for (unsigned f = 0; f < data.length(); f += 9)
869  {
870  if (f + 9 > data.length())
871  break;
872 
873  const int id = decodeStr(data.substr(f, 2));
874  const int price = decodeStr(data.substr(f + 2, 4));
875  int amount = decodeStr(data.substr(f + 6, 3));
876  if (buyDialog != nullptr && amount > 0)
877  {
878  buyDialog->addItem(id,
881  amount,
882  price);
883  }
884  if (sellDialog != nullptr)
885  {
886  const Item *const item = inv->findItem(id, ItemColor_zero);
887  if (item != nullptr)
888  {
889  if (item->getQuantity() < amount)
890  amount = item->getQuantity();
891  }
892  else
893  {
894  amount = 0;
895  }
896  ShopItem *const shopItem = sellDialog->addItem(id,
899  amount,
900  price);
901 
902  if (shopItem != nullptr && amount <= 0)
903  shopItem->setDisabled(true);
904  }
905  }
906  if (buyDialog != nullptr)
907  buyDialog->sort();
908 }
909 
910 void ShopWindow::processRequest(const std::string &nick,
911  std::string data,
912  const int mode)
913 {
914  if (localPlayer == nullptr ||
915  !mTradeNick.empty() ||
917  actorManager == nullptr ||
919  {
920  return;
921  }
922 
923  const Inventory *const inv = PlayerInfo::getInventory();
924  if (inv == nullptr)
925  return;
926 
927  const size_t idx = data.find(' ');
928  if (idx == std::string::npos)
929  return;
930 
932  return;
933 
934  if (!mTradeNick.empty())
935  {
936  sendMessage(nick,
937  // TRANSLATORS: error buy/sell shop request
938  _("error: player busy") + std::string(" "),
939  true);
940  return;
941  }
942 
943  data = data.substr(idx + 1);
944 
945  std::string part1;
946  std::string part2;
947  std::string part3;
948  std::stringstream ss(data);
949  int id;
950  int price;
951  int amount;
952 
953  if (!(ss >> part1))
954  return;
955 
956  if (!(ss >> part2))
957  return;
958 
959  if (!(ss >> part3))
960  return;
961 
962  id = atoi(part1.c_str());
963  price = atoi(part2.c_str());
964  amount = atoi(part3.c_str());
965 
966  delete mTradeItem;
967  // +++ need impliment colors?
968  mTradeItem = new ShopItem(-1,
969  id,
972  amount,
973  price,
975 
976  if (mode == BUY)
977  {
978  // +++ need support for colors
979  const Item *const item2 = inv->findItem(mTradeItem->getId(),
981  if (item2 == nullptr ||
982  item2->getQuantity() < amount ||
983  !findShopItem(mTradeItem, SELL))
984  {
985  sendMessage(nick,
986  // TRANSLATORS: error buy/sell shop request
987  _("error: Can't sell this item") + std::string(" "),
988  true);
989  return;
990  }
991  mTradeMoney = 0;
992  }
993  else
994  {
995  if (!findShopItem(mTradeItem, BUY))
996  {
997  sendMessage(nick,
998  // TRANSLATORS: error buy/sell shop request
999  _("error: Can't buy this item") + std::string(" "),
1000  true);
1001  return;
1002  }
1003  mTradeMoney = mTradeItem->getPrice() * mTradeItem->getQuantity();
1004  }
1005 
1006  mTradeNick = nick;
1007 
1008  if (config.getBoolValue("autoShop"))
1009  {
1011  startTrade();
1012  }
1013  else
1014  {
1015  std::string msg;
1016  if (mode == BUY)
1017  {
1018  // TRANSLATORS: buy shop request (nick, item)
1019  msg = strprintf(_("%s wants to buy %s do you accept?"),
1020  nick.c_str(),
1021  mTradeItem->getInfo().getName().c_str());
1022  }
1023  else
1024  {
1025  // TRANSLATORS: sell shop request (nick, item)
1026  msg = strprintf(_("%s wants to sell %s do you accept?"),
1027  nick.c_str(),
1028  mTradeItem->getInfo().getName().c_str());
1029  }
1030 
1032  // TRANSLATORS: shop window dialog
1033  _("Request for Trade"),
1034  msg,
1035  SOUND_REQUEST,
1036  true,
1037  Modal_false,
1038  nullptr);
1039  confirmDlg->addActionListener(this);
1040  }
1041 }
1042 
1044 {
1045  BLOCK_START("ShopWindow::updateTimes")
1046  if (mAnnounceButton == nullptr)
1047  {
1048  BLOCK_END("ShopWindow::updateTimes")
1049  return;
1050  }
1051  if (mAnnonceTime + (2 * 60) < cur_time ||
1053  {
1054  mAnnounceButton->setEnabled(true);
1055  }
1056  BLOCK_END("ShopWindow::updateTimes")
1057 }
1058 
1059 bool ShopWindow::checkFloodCounter(time_t &counterTime)
1060 {
1061  if (counterTime == 0 || counterTime > cur_time)
1062  counterTime = cur_time;
1063  else if (counterTime + 10 > cur_time)
1064  return false;
1065  else
1066  counterTime = cur_time;
1067  return true;
1068 }
1069 
1070 bool ShopWindow::findShopItem(const ShopItem *const shopItem,
1071  const int mode) const
1072 {
1073  if (shopItem == nullptr)
1074  return false;
1075 
1076  STD_VECTOR<ShopItem*> items;
1077  if (mode == SELL)
1078  items = mSellShopItems->items();
1079  else
1080  items = mBuyShopItems->items();
1081 
1082  FOR_EACH (STD_VECTOR<ShopItem*>::const_iterator, it, items)
1083  {
1084  const ShopItem *const item = *(it);
1085  if (item == nullptr)
1086  continue;
1087 
1088  if (item->getId() == shopItem->getId()
1089  && item->getPrice() == shopItem->getPrice()
1090  && item->getQuantity() >= shopItem->getQuantity())
1091  {
1092  return true;
1093  }
1094  }
1095  return false;
1096 }
1097 #endif // TMWA_SUPPORT
1098 
1099 int ShopWindow::sumAmount(const Item *const shopItem)
1100 {
1101  if ((localPlayer == nullptr) || (shopItem == nullptr))
1102  return 0;
1103 
1104  const Inventory *const inv = PlayerInfo::getInventory();
1105  if (inv == nullptr)
1106  return 0;
1107  int sum = 0;
1108 
1109  for (unsigned f = 0; f < inv->getSize(); f ++)
1110  {
1111  const Item *const item = inv->getItem(f);
1112  if ((item != nullptr) && item->getId() == shopItem->getId())
1113  sum += item->getQuantity();
1114  }
1115  return sum;
1116 }
1117 
1119 {
1120  if (mBuyShopItems->empty() && mSellShopItems->empty())
1121  return true;
1122  return false;
1123 }
1124 
1126 {
1127  if (isBuySelected)
1129  else
1133 }
1134 
1136 {
1137  if (mSellShopName.empty())
1138  {
1139  // TRANSLATORS: shop window name
1140  setCaption(_("Personal Shop"));
1141  }
1142  else
1143  {
1144  // TRANSLATORS: shop window name
1145  setCaption(strprintf(_("Personal Shop - %s"), mSellShopName.c_str()));
1146  }
1147 }
1148 
1149 void ShopWindow::setShopName(const std::string &name)
1150 {
1151  mSellShopName = name;
1152  serverConfig.setValue("sellShopName", mSellShopName);
1153  updateShopName();
1154 }
1155 
1156 void ShopWindow::vendingSlotsChanged(const int slots)
1157 {
1158  mSellShopSize = slots;
1160 }
1161 
1162 void ShopWindow::vendingEnabled(const bool b)
1163 {
1164  mEnableVending = b;
1165  localPlayer->enableShop(b);
1166  if (!b)
1167  mSellShopSize = 0;
1169 }
1170 
1172 {
1173  mBuyShopSize = slots;
1175 }
1176 
1178 {
1179  mEnableBuyingStore = b;
1180  localPlayer->enableShop(b);
1181  if (!b)
1182  mBuyShopSize = 0;
1184 }
Button * mDeleteButton
Definition: shopwindow.h:183
int getInvIndex() const
Definition: item.h:164
ShopListBox * mSellShopItemList
Definition: shopwindow.h:179
ChatWindow * chatWindow
Definition: chatwindow.cpp:88
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
void setDefaultSize()
Definition: window.cpp:1193
int mBuyShopSize
Definition: shopwindow.h:199
bool mHaveVending
Definition: shopwindow.h:201
Button * mRenameButton
Definition: shopwindow.h:186
#define _(s)
Definition: gettext.h:34
bool isBuySelected
Definition: shopwindow.h:200
void loadList()
Definition: shopwindow.cpp:532
void addAutoMoney(const std::string &nick, const int money)
Button * mPublishButton
Definition: shopwindow.h:185
void action(const ActionEvent &event)
Definition: shopwindow.cpp:247
std::string mSellShopName
Definition: shopwindow.h:191
bool mEnableVending
Definition: shopwindow.h:203
Button * mAddButton
Definition: shopwindow.h:182
ShopItem * addItem(const int id, const ItemTypeT type, const ItemColor color, const int amount, const int price)
Definition: shopitems.cpp:58
TradeWindow * tradeWindow
Definition: tradewindow.cpp:64
ShopItems * mBuyShopItems
Definition: shopwindow.h:174
void buyingStoreSlotsChanged(const int slots)
ShopItem * mTradeItem
Definition: shopwindow.h:176
void loadWindowState()
Definition: window.cpp:1082
void setPriceCheck(const bool check)
virtual void addButton(const std::string &text, const std::string &tag, const bool pressed)
Definition: widgetgroup.cpp:41
const std::string encodeStr(unsigned int value, const unsigned int size)
virtual void create(const std::string &name, const int maxMoney, const bool flag, const std::vector< ShopItem *> &items) const =0
void ignoreTrade(const std::string &name) const
Item * findItem(const int itemId, const ItemColor color) const
Definition: inventory.cpp:93
void addActionListener(ActionListener *const actionListener)
Definition: widget.cpp:251
void vendingEnabled(const bool b)
virtual void close() const =0
bool empty() const
Definition: shopitems.h:101
void updateStatus() const
Inventory * getInventory()
Definition: playerinfo.cpp:192
void addSelectionListener(SelectionListener *const selectionListener)
Definition: listbox.cpp:434
void setMinWidth(const int width)
Definition: window.cpp:586
Definition: window.h:98
int mWidth
Definition: graphics.h:483
#define BLOCK_START(name)
Definition: perfomance.h:78
Definition: button.h:94
SoundManager soundManager
Configuration config
static void showWindow(const ItemAmountWindowUsageT usage, Window *const parent, Item *const item, int maxRange, const int tag)
int getOption(const std::string &name, const int def) const
Definition: window.cpp:1449
static const std::string SOUND_REQUEST
Definition: sound.h:28
void saveList() const
Definition: shopwindow.cpp:595
virtual void createShop(const std::string &name, const bool flag, const std::vector< ShopItem *> &items) const =0
#define BLOCK_END(name)
Definition: perfomance.h:79
bool msg(InputEvent &event)
Definition: chat.cpp:38
const ItemColor ItemColor_zero
Definition: itemcolor.h:29
int getIntValue(const std::string &key) const
int mTradeMoney
Definition: shopwindow.h:197
const ItemColor ItemColor_one
Definition: itemcolor.h:29
void setActionEventId(const std::string &actionEventId)
Definition: widget.h:595
#define CREATEWIDGETV(var, type,...)
Definition: createwidget.h:24
const std::string & getName() const
Definition: iteminfo.h:73
#define delete2(var)
Definition: delete2.h:24
ShopListBox * mCurrentShopItemList
Definition: shopwindow.h:180
Configuration serverConfig
ShopListBox * mBuyShopItemList
Definition: shopwindow.h:178
void vendingSlotsChanged(const int slots)
std::string tradePartnerName
Definition: popupmenu.cpp:100
void processRequest(const std::string &nick, std::string data, const int mode)
Definition: shopwindow.cpp:910
void registerWindowForReset(Window *const window)
void adjustSize()
Definition: button.cpp:829
ShopItem * addItem(const int id, const ItemTypeT type, const ItemColor color, const int amount, const int price)
Definition: buydialog.cpp:448
void clear()
Definition: shopitems.cpp:173
static int sumAmount(const Item *const shopItem)
static void distributeEvent(const bool b)
void startTrade()
Definition: shopwindow.cpp:720
void setSelectable(const bool selectable)
Definition: widget.h:947
virtual void close()
Definition: window.cpp:897
#define new
Definition: debug_new.h:147
Settings settings
Definition: settings.cpp:31
bool mEnableBuyingStore
Definition: shopwindow.h:202
void setShopName(const std::string &name)
bool getBoolValue(const std::string &key) const
void setCaption(const std::string &caption)
Definition: button.h:214
void buyingStoreEnabled(const bool b)
std::vector< ShopItem * > & items()
Definition: shopitems.h:135
Inventory * getCartInventory()
Definition: playerinfo.cpp:204
virtual void privateMessage(const std::string &recipient, const std::string &text) const =0
void giveList(const std::string &nick, const int mode)
Definition: shopwindow.cpp:745
const std::string DEFAULT_CURRENCY
Definition: currency.h:26
std::string strprintf(const char *const format,...)
Definition: stringutils.cpp:99
time_t mLastRequestTimeItem
Definition: shopwindow.h:195
void sort()
Definition: buydialog.cpp:463
int mSellShopSize
Definition: shopwindow.h:198
int getPrice() const
Definition: shopitem.h:131
const bool Visible_false
Definition: visible.h:29
void announce(ShopItems *const list, const int mode)
Definition: shopwindow.cpp:661
int getQuantity() const
Definition: item.h:104
#define fromBool(val, name)
Definition: booldefines.h:48
std::string serverConfigDir
Definition: settings.h:115
void addBuyItem(const Item *const item, const int amount, const int price)
Definition: shopwindow.cpp:498
uint32_t data
time_t mAnnonceTime
Definition: shopwindow.h:193
void updateTimes()
void setMoney(const int amount)
Definition: selldialog.cpp:318
LocalPlayer * localPlayer
ItemColor getColor() const
Definition: item.h:180
std::string mTradeNick
Definition: shopwindow.h:190
static void showList(const std::string &nick, std::string data)
Definition: shopwindow.cpp:840
int getSelected() const
Definition: listbox.h:167
Definition: item.h:48
static void distributeEvent(const bool b)
void setInvIndex(const int index)
Definition: item.h:158
#define nullptr
Definition: localconsts.h:44
Graphics * mainGraphics
Definition: graphics.cpp:108
int mSelectedItem
Definition: shopwindow.h:192
void updateButtonsAndLabels()
Definition: shopwindow.cpp:425
void setCloseButton(const bool flag)
Definition: window.cpp:744
void sendMessage(const std::string &nick, std::string data, const bool random)
Definition: shopwindow.cpp:819
const ItemInfo & getInfo() const
Definition: item.h:170
volatile time_t cur_time
Definition: timer.cpp:57
void addItem(const Item *const item, const int price)
Definition: selldialog.cpp:216
ShopRenameListener shopRenameListener
void setContent(Widget *widget)
void enableVisibleSound(bool b)
Definition: window.h:480
void valueChanged(const SelectionEvent &event)
Definition: shopwindow.cpp:420
void setMinHeight(const int height)
Definition: window.cpp:599
ContainerPlacer getPlacer(const int x, const int y)
Definition: window.cpp:1386
void setEnabled(const bool enabled)
Definition: widget.h:351
void enableShop(const bool b)
Definition: being.cpp:5314
Layout & getLayout()
Definition: window.cpp:1360
Button * mAnnounceButton
Definition: shopwindow.h:184
Net::BuyingStoreHandler * buyingStoreHandler
Definition: net.cpp:98
ShopWindow * shopWindow
Definition: shopwindow.cpp:99
ServerTypeT getNetworkType()
Definition: net.cpp:178
unsigned int decodeStr(const std::string &str)
TabStrip * mTabs
Definition: shopwindow.h:188
void updateShopName()
int getId() const
Definition: item.h:80
#define A_UNUSED
Definition: localconsts.h:171
virtual void setVisible(Visible visible)
Definition: window.cpp:773
void center()
Definition: window.cpp:1412
void addAutoItem(const std::string &nick, Item *const item, const int amount)
ConfirmDialog * confirmDlg
Definition: traderecv.cpp:48
Net::ChatHandler * chatHandler
Definition: net.cpp:80
ShopItem * addItemNoDup(const int id, const ItemTypeT type, const ItemColor color, const int amount, const int price)
Definition: shopitems.cpp:76
std::list< ShopWindow * > DialogList
Definition: shopwindow.h:169
Net::TradeHandler * tradeHandler
Definition: net.cpp:91
void setDisabled(const bool b)
Definition: shopitem.h:153
void updateSelection()
bool isShopEmpty() const
ScrollArea * mScrollArea
Definition: shopwindow.h:181
time_t mLastRequestTimeList
Definition: shopwindow.h:194
void setMoney(const int amount)
Definition: buydialog.cpp:428
ItemTypeT getType() const
Definition: item.h:224
Button * mCloseButton
Definition: shopwindow.h:172
static DialogList instances
Definition: shopwindow.h:170
void setQuantity(const int quantity)
Definition: item.h:92
static const std::string SOUND_TRADE
Definition: sound.h:29
Being * findBeingByName(const std::string &name, const ActorTypeT type) const
void setResizable(const bool resize)
Definition: window.cpp:622
void del(const unsigned int i)
Definition: shopitems.cpp:160
Net::VendingHandler * vendingHandler
Definition: net.cpp:111
void setStickyButtonLock(const bool sticky)
Definition: window.cpp:767
SetupWindow * setupWindow
Definition: setupwindow.cpp:63
virtual void channelMessage(const std::string &channel, const std::string &text) const =0
virtual void request(const Being *const being) const
Definition: tradehandler.h:45
#define CREATEWIDGETR(type,...)
Definition: createwidget.h:35
const std::string TRADE_CHANNEL
Definition: chat.h:30
bool findShopItem(const ShopItem *const shopItem, const int mode) const
const bool Trading_true
Definition: trading.h:29
Item * getItem(const int index) const
Definition: inventory.cpp:82
Definition: layout.h:43
static bool checkFloodCounter(time_t &counterTime)
int32_t getAttribute(const AttributesT id)
Definition: playerinfo.cpp:100
CheckBox * mAnnounceLinks
Definition: shopwindow.h:187
void setCaption(const std::string &caption)
Definition: window.h:530
Definition: being.h:93
bool isSelected() const
Definition: checkbox.h:146
PlayerRelationsManager playerRelations
void setRowHeight(const int n, const int h)
Definition: layoutcell.cpp:127
void setDialog(EditDialog *const dialog)
#define reportAlways(...)
Definition: checkutils.h:252
void addSellItem(const Item *const item, const int amount, const int price)
Definition: shopwindow.cpp:515
virtual void close() const =0
bool getHaveCart() const
Definition: actorsprite.h:174
void setValue(const std::string &key, const std::string &value)
void postInit()
Definition: shopwindow.cpp:226
void addWhisper(const std::string &nick, const std::string &mes, const ChatMsgTypeT own)
void postInit()
Definition: window.cpp:248
ActorManager * actorManager
ShopItems * mSellShopItems
Definition: shopwindow.h:175
void playGuiSound(const std::string &name)
void setWindowName(const std::string &name)
Definition: window.h:354
int getNumberOfElements()
Definition: shopitems.h:98
unsigned getSize() const
Definition: inventory.h:75
int mRandCounter
Definition: shopwindow.h:196
Trading isTrading()
Definition: playerinfo.cpp:388
void setHorizontalScrollPolicy(const ScrollPolicy hPolicy)
void setVisible(Visible visible)
Definition: shopwindow.cpp:493