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