ManaPlus
tradewindow.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 
25 
26 #include "configuration.h"
27 #include "game.h"
28 
29 #include "being/localplayer.h"
30 #include "being/playerinfo.h"
31 #include "being/playerrelations.h"
32 
33 #include "enums/gui/layouttype.h"
34 
35 #include "gui/gui.h"
36 
37 #include "gui/fonts/font.h"
38 
42 
43 #include "gui/widgets/button.h"
46 #include "gui/widgets/label.h"
47 #include "gui/widgets/layout.h"
48 #include "gui/widgets/scrollarea.h"
49 #include "gui/widgets/textfield.h"
50 
52 
53 #include "resources/db/unitsdb.h"
54 
55 #include "resources/item/item.h"
56 
57 #include "net/net.h"
58 #include "net/tradehandler.h"
59 
60 #include "utils/delete2.h"
61 #include "utils/gettext.h"
62 
63 #include "debug.h"
64 
66 
67 // TRANSLATORS: trade window button
68 #define CAPTION_PROPOSE _("Propose trade")
69 // TRANSLATORS: trade window button
70 #define CAPTION_CONFIRMED _("Confirmed. Waiting...")
71 // TRANSLATORS: trade window button
72 #define CAPTION_ACCEPT _("Agree trade")
73 // TRANSLATORS: trade window button
74 #define CAPTION_ACCEPTED _("Agreed. Waiting...")
75 
77  // TRANSLATORS: trade window caption
78  Window(_("Trade: You"), Modal_false, nullptr, "trade.xml"),
81  mMyInventory(new Inventory(InventoryType::Trade, -1)),
82  mPartnerInventory(new Inventory(InventoryType::Trade, -1)),
83  mMyItemContainer(new ItemContainer(this, mMyInventory, 100000,
85  mPartnerItemContainer(new ItemContainer(this, mPartnerInventory, 100000,
87  // TRANSLATORS: trade window money label
88  mMoneyLabel(new Label(this, strprintf(_("You get %s"), ""))),
89  // TRANSLATORS: trade window button
90  mAddButton(new Button(this, _("Add"), "add", BUTTON_SKIN, this)),
91  mOkButton(new Button(this, "", "",
92  BUTTON_SKIN, this)), // Will be filled in later
93  // TRANSLATORS: trade window money change button
94  mMoneyChangeButton(new Button(this, _("Change"), "money",
95  BUTTON_SKIN, this)),
96  mMoneyField(new TextField(this, std::string(),
97  LoseFocusOnTab_true, nullptr, std::string(), false)),
98  mAutoAddItem(nullptr),
99  mAutoAddToNick(""),
100  mGotMoney(0),
101  mGotMaxMoney(0),
102  mAutoMoney(0),
103  mAutoAddAmount(0),
104  mStatus(PROPOSING),
105  mOkOther(false),
106  mOkMe(false)
107 {
108  setWindowName("Trade");
109  setResizable(true);
110  setCloseButton(true);
111  setStickyButtonLock(true);
112  setDefaultSize(386, 180, ImagePosition::CENTER, 0, 0);
113  setMinWidth(310);
114  setMinHeight(180);
115 
116  if (setupWindow != nullptr)
118 
119  const Font *const fnt = mOkButton->getFont();
120  int width = std::max(fnt->getWidth(CAPTION_PROPOSE),
122  width = std::max(width, fnt->getWidth(CAPTION_ACCEPT));
123  width = std::max(width, fnt->getWidth(CAPTION_ACCEPTED));
124 
125  mOkButton->setWidth(8 + width);
126 
128 
129  ScrollArea *const myScroll = new ScrollArea(this, mMyItemContainer,
130  Opaque_true, "trade_background.xml");
132 
134 
135  ScrollArea *const partnerScroll = new ScrollArea(this,
137  Opaque_true, "trade_background.xml");
139 
140  // TRANSLATORS: trade window money label
141  Label *const moneyLabel2 = new Label(this, _("You give:"));
142 
143  mMoneyField->setWidth(40);
144 
145  place(1, 0, mMoneyLabel, 1, 1);
146  place(0, 1, myScroll, 1, 1).setPadding(3);
147  place(1, 1, partnerScroll, 1, 1).setPadding(3);
148  ContainerPlacer placer = getPlacer(0, 0);
149  placer(0, 0, moneyLabel2, 1, 1);
150  placer(1, 0, mMoneyField, 2, 1);
151  placer(3, 0, mMoneyChangeButton, 1, 1).setHAlign(LayoutCell::LEFT);
152  placer = getPlacer(0, 2);
153  placer(0, 0, mAddButton, 1, 1);
154  placer(1, 0, mOkButton, 1, 1);
155  Layout &layout = getLayout();
156  layout.extend(0, 2, 2, 1);
157  layout.setRowHeight(1, LayoutType::SET);
158  layout.setRowHeight(2, 0);
159  layout.setColWidth(0, LayoutType::SET);
160  layout.setColWidth(1, LayoutType::SET);
161 
162  loadWindowState();
163  enableVisibleSound(true);
164 
165  reset();
166 }
167 
169 {
172 }
173 
174 void TradeWindow::setMoney(const int amount)
175 {
176  if (amount < 0 || amount < mGotMaxMoney)
177  {
178  if (config.getBoolValue("securetrades"))
179  {
180  close();
181  return;
182  }
184  getThemeColor(ThemeColorId::WARNING, 255U),
185  getThemeColor(ThemeColorId::WARNING_OUTLINE, 255U));
186  }
187  else
188  {
191  getThemeColor(ThemeColorId::LABEL_OUTLINE, 255U));
192  mGotMaxMoney = amount;
193  }
194 
195  mGotMoney = amount;
196  // TRANSLATORS: trade window money label
197  mMoneyLabel->setCaption(strprintf(_("You get %s"),
198  UnitsDb::formatCurrency(amount).c_str()));
200 }
201 
202 void TradeWindow::addItem(const int id,
203  const ItemTypeT type,
204  const bool own,
205  const int quantity,
206  const uint8_t refine,
207  const ItemColor color,
208  const Identified identified,
209  const Damaged damaged,
210  const Favorite favorite) const
211 {
212  Inventory *const inv = own ? mMyInventory : mPartnerInventory;
213  inv->addItem(id,
214  type,
215  quantity,
216  refine,
217  color,
218  identified,
219  damaged,
220  favorite,
221  Equipm_false,
223 }
224 
225 void TradeWindow::addItem2(const int id,
226  const ItemTypeT type,
227  const int *const cards,
228  const ItemOptionsList *const options,
229  const int sz,
230  const bool own,
231  const int quantity,
232  const uint8_t refine,
233  const ItemColor color,
234  const Identified identified,
235  const Damaged damaged,
236  const Favorite favorite,
237  const Equipm equipment) const
238 {
239  Inventory *const inv = own ? mMyInventory : mPartnerInventory;
240  const int slot = inv->addItem(id,
241  type,
242  quantity,
243  refine,
244  color,
245  identified,
246  damaged,
247  favorite,
248  equipment,
250  if (slot >= 0)
251  {
252  inv->setCards(slot, cards, sz);
253  inv->setOptions(slot, options);
254  }
255 }
256 
257 void TradeWindow::changeQuantity(const int index, const bool own,
258  const int quantity) const
259 {
260  Item *item;
261  if (own)
262  item = mMyInventory->getItem(index);
263  else
264  item = mPartnerInventory->getItem(index);
265  if (item != nullptr)
266  item->setQuantity(quantity);
267 }
268 
269 void TradeWindow::increaseQuantity(const int index, const bool own,
270  const int quantity) const
271 {
272  Item *item;
273  if (own)
274  item = mMyInventory->getItem(index);
275  else
276  item = mPartnerInventory->getItem(index);
277  if (item != nullptr)
278  item->increaseQuantity(quantity);
279 }
280 
282 {
283  mMyInventory->clear();
285  mOkOther = false;
286  mOkMe = false;
287  setMoney(0);
288  mMoneyField->setEnabled(true);
289  mMoneyField->setText("");
292  getThemeColor(ThemeColorId::LABEL_OUTLINE, 255U));
293  mAddButton->setEnabled(true);
295  mGotMoney = 0;
296  mGotMaxMoney = 0;
298 }
299 
300 void TradeWindow::receivedOk(const bool own)
301 {
302  if (own)
303  mOkMe = true;
304  else
305  mOkOther = true;
306 
307  if (mOkMe && mOkOther)
309 }
310 
312 {
313  if (config.getBoolValue("tradescreenshot"))
314  Game::createScreenshot(std::string());
316  reset();
317 }
318 
319 void TradeWindow::tradeItem(const Item *const item, const int quantity,
320  const bool check) const
321 {
322  if (check && !checkItem(item))
323  return;
324 
325  tradeHandler->addItem(item, quantity);
326 }
327 
329 {
330  if ((mMyItemContainer == nullptr) || (mPartnerItemContainer == nullptr))
331  return;
332 
333  /* If an item is selected in one container, make sure no item is selected
334  * in the other container.
335  */
336  if (event.getSource() == mMyItemContainer &&
337  (mMyItemContainer->getSelectedItem() != nullptr))
338  {
340  }
341  else if (mPartnerItemContainer->getSelectedItem() != nullptr)
342  {
344  }
345 }
346 
348 {
349  if (s == mStatus)
350  return;
351  mStatus = s;
352 
353  switch (s)
354  {
355  case PREPARING:
358  break;
359  case PROPOSING:
362  break;
363  case ACCEPTING:
365  mOkButton->setActionEventId("trade");
366  break;
367  case ACCEPTED:
370  break;
371  default:
372  break;
373  }
374 
375  mOkButton->setEnabled((s != PROPOSING && s != ACCEPTED));
376 }
377 
379 {
380  if (inventoryWindow == nullptr)
381  return;
382 
383  Item *const item = inventoryWindow->getSelectedItem();
384  const std::string &eventId = event.getId();
385 
386  if (eventId == "add")
387  {
388  if (mStatus != PREPARING)
389  return;
390 
392  {
394  return;
395  }
396 
397  if (item == nullptr)
398  return;
399 
400  if (mMyInventory->getFreeSlot() == -1)
401  return;
402 
403  if (!checkItem(item))
404  return;
405 
406  // Choose amount of items to trade
408  this,
409  item,
410  0,
411  0);
412 
414  }
415  else if (eventId == "cancel")
416  {
418  reset();
420  tradeHandler->cancel();
421  }
422  else if (eventId == "ok")
423  {
424  mMoneyField->setEnabled(false);
425  mAddButton->setEnabled(false);
427  receivedOk(true);
430  }
431  else if (eventId == "trade")
432  {
433  receivedOk(true);
435  tradeHandler->finish();
436  }
437  else if (eventId == "money")
438  {
439  if (mStatus != PREPARING)
440  return;
441 
442  int v = atoi(mMoneyField->getText().c_str());
443  const int curMoney = PlayerInfo::getAttribute(Attributes::MONEY);
444  if (v > curMoney)
445  {
446  if (localChatTab != nullptr)
447  {
448  // TRANSLATORS: trade error
449  localChatTab->chatLog(_("You don't have enough money."),
453  }
454  v = curMoney;
455  }
457  mMoneyField->setText(strprintf("%d", v));
458  }
459 }
460 
462 {
463  tradeHandler->cancel();
464  clear();
465 }
466 
468 {
469  mAutoAddItem = nullptr;
470  mAutoAddToNick.clear();
471  mAutoMoney = 0;
472  mAutoAddAmount = 0;
473  mGotMoney = 0;
474  mGotMaxMoney = 0;
477  getThemeColor(ThemeColorId::LABEL_OUTLINE, 255U));
478 }
479 
480 void TradeWindow::addAutoItem(const std::string &nick, Item* const item,
481  const int amount)
482 {
483  mAutoAddToNick = nick;
484  mAutoAddItem = item;
485  mAutoAddAmount = amount;
486 }
487 
488 void TradeWindow::addAutoMoney(const std::string &nick, const int money)
489 {
490  mAutoAddToNick = nick;
491  mAutoMoney = money;
492 }
493 
494 void TradeWindow::initTrade(const std::string &nick)
495 {
496  if (localPlayer == nullptr)
497  return;
498 
499  if (!mAutoAddToNick.empty() && mAutoAddToNick == nick)
500  {
501  if ((mAutoAddItem != nullptr) && (mAutoAddItem->getQuantity() != 0))
502  {
503  const Inventory *const inv = PlayerInfo::getInventory();
504  if (inv != nullptr)
505  {
506  const Item *const item = inv->findItem(mAutoAddItem->getId(),
508  if (item != nullptr)
509  tradeItem(item, mAutoAddAmount, false);
510  }
511  }
512  if (mAutoMoney != 0)
513  {
516  }
517  }
518  clear();
519  if (!playerRelations.isGoodName(nick))
521 }
522 
523 bool TradeWindow::checkItem(const Item *const item) const
524 {
525  if (item == nullptr)
526  return false;
527 
528  const int itemId = item->getId();
529  if (PlayerInfo::isItemProtected(itemId))
530  return false;
531  const Item *const tItem = mMyInventory->findItem(
532  itemId, item->getColor());
533 
534  if ((tItem != nullptr) && (tItem->getQuantity() > 1
535  || item->getQuantity() > 1))
536  {
537  if (localChatTab != nullptr)
538  {
539  // TRANSLATORS: trade error
540  localChatTab->chatLog(_("Failed adding item. You can not "
541  "overlap one kind of item on the window."),
545  }
546  return false;
547  }
549  item->isEquipped() == Equipped_true)
550  {
551  if (localChatTab != nullptr)
552  {
554  // TRANSLATORS: trade error
555  _("Failed adding item. You can not trade equipped items."),
559  }
560  return false;
561  }
562  return true;
563 }
564 
566 {
567  return mMoneyField != nullptr && mMoneyField->isFocused();
568 }
const std::string BUTTON_SKIN
Definition: button.h:89
ChatTab * localChatTab
Definition: chattab.cpp:62
Definition: button.h:102
void setCaption(const std::string &caption)
Definition: button.h:214
void chatLog(std::string line, ChatMsgTypeT own, const IgnoreRecord ignoreRecord, const TryRemoveColors tryRemoveColors)
Definition: chattab.cpp:111
bool getBoolValue(const std::string &key) const
Widget * getSource() const
Definition: event.h:104
Definition: font.h:90
int getWidth(const std::string &text) const
Definition: font.cpp:334
static bool createScreenshot(const std::string &prefix)
Definition: game.cpp:535
Font * getSecureFont() const
Definition: gui.h:172
void setVisible(Visible visible)
Item * getSelectedItem() const
void setCards(const int index, const int *const cards, const int size) const
Definition: inventory.cpp:194
void clear()
Definition: inventory.cpp:238
Item * getItem(const int index) const
Definition: inventory.cpp:83
void setOptions(const int index, const ItemOptionsList *const options)
Definition: inventory.cpp:210
Item * findItem(const int itemId, const ItemColor color) const
Definition: inventory.cpp:94
int addItem(const int id, const ItemTypeT type, const int quantity, const uint8_t refine, const ItemColor color, const Identified identified, const Damaged damaged, const Favorite favorite, const Equipm equipment, const Equipped equipped)
Definition: inventory.cpp:115
int getFreeSlot() const
Definition: inventory.cpp:282
static void showWindow(const ItemAmountWindowUsageT usage, Window *const parent, Item *const item, int maxRange, const int tag)
void addSelectionListener(SelectionListener *listener)
Item * getSelectedItem() const
Definition: item.h:50
void setQuantity(const int quantity)
Definition: item.h:93
int getQuantity() const
Definition: item.h:105
Equipped isEquipped() const
Definition: item.h:129
int getId() const
Definition: item.h:81
ItemColor getColor() const
Definition: item.h:181
void increaseQuantity(const int amount)
Definition: item.h:99
Definition: label.h:91
void adjustSize()
Definition: label.cpp:200
void setForegroundColorAll(const Color &color1, const Color &color2)
Definition: label.cpp:217
void setCaption(const std::string &caption)
Definition: label.cpp:264
void extend(const int x, const int y, const int w, const int h)
Definition: layoutcell.cpp:133
LayoutCell & setPadding(int p)
Definition: layoutcell.h:60
void setRowHeight(const int n, const int h)
Definition: layoutcell.cpp:128
void setColWidth(const int n, const int w)
Definition: layoutcell.cpp:123
Definition: layout.h:45
virtual void setMoney(const int amount) const
Definition: tradehandler.h:60
virtual void confirm() const
Definition: tradehandler.h:63
virtual void cancel() const
Definition: tradehandler.h:69
virtual void addItem(const Item *const item, const int amount) const
Definition: tradehandler.h:52
virtual void finish() const
Definition: tradehandler.h:66
bool isGoodName(Being *const being) const
void setHorizontalScrollPolicy(const ScrollPolicy hPolicy)
void registerWindowForReset(Window *const window)
const std::string & getText() const
Definition: textfield.h:224
void setText(const std::string &text)
Definition: textfield.cpp:803
Status mStatus
Definition: tradewindow.h:208
TextField * mMoneyField
Definition: tradewindow.h:200
Label * mMoneyLabel
Definition: tradewindow.h:196
Button * mOkButton
Definition: tradewindow.h:198
std::string mAutoAddToNick
Definition: tradewindow.h:203
void valueChanged(const SelectionEvent &event)
Button * mMoneyChangeButton
Definition: tradewindow.h:199
int mAutoAddAmount
Definition: tradewindow.h:207
Item * mAutoAddItem
Definition: tradewindow.h:202
int mGotMaxMoney
Definition: tradewindow.h:205
ItemContainer * mPartnerItemContainer
Definition: tradewindow.h:194
void addAutoMoney(const std::string &nick, const int money)
bool isInpupFocused() const
void addItem(const int id, const ItemTypeT type, const bool own, const int quantity, const uint8_t refine, const ItemColor color, const Identified identified, const Damaged damaged, const Favorite favorite) const
ItemContainer * mMyItemContainer
Definition: tradewindow.h:193
Button * mAddButton
Definition: tradewindow.h:197
void setMoney(const int quantity)
void receivedOk(const bool own)
void initTrade(const std::string &nick)
void completeTrade()
Inventory * mPartnerInventory
Definition: tradewindow.h:191
void setStatus(const Status s)
void action(const ActionEvent &event)
bool checkItem(const Item *const item) const
void changeQuantity(const int index, const bool own, const int quantity) const
void addItem2(const int id, const ItemTypeT type, const int *const cards, const ItemOptionsList *const options, const int sz, const bool own, const int quantity, const uint8_t refine, const ItemColor color, const Identified identified, const Damaged damaged, const Favorite favorite, const Equipm equipment) const
void increaseQuantity(const int index, const bool own, const int quantity) const
Inventory * mMyInventory
Definition: tradewindow.h:190
void tradeItem(const Item *const item, const int quantity, const bool check) const
void addAutoItem(const std::string &nick, Item *const item, const int amount)
const Color & getThemeColor(const ThemeColorIdT type, const unsigned int alpha) const A_INLINE
Definition: widget2.h:45
void setWidth(const int width)
Definition: widget.cpp:133
void setEnabled(const bool enabled)
Definition: widget.h:352
void setActionEventId(const std::string &actionEventId)
Definition: widget.h:596
Font * getFont() const
Definition: widget.cpp:331
virtual bool isFocused() const
Definition: widget.cpp:184
Definition: window.h:102
void setResizable(const bool resize)
Definition: window.cpp:627
ContainerPlacer getPlacer(const int x, const int y)
Definition: window.cpp:1391
virtual void setVisible(Visible visible)
Definition: window.cpp:778
bool isWindowVisible() const
Definition: window.h:484
Layout & getLayout()
Definition: window.cpp:1365
void setWindowName(const std::string &name)
Definition: window.h:355
void setCaptionFont(Font *font)
Definition: window.h:478
void setMinHeight(const int height)
Definition: window.cpp:604
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
LayoutCell & place(const int x, const int y, Widget *const wg, const int w, const int h)
Definition: window.cpp:1384
void setDefaultSize()
Definition: window.cpp:1198
void loadWindowState()
Definition: window.cpp:1087
Configuration config
bool Damaged
Definition: damaged.h:30
#define new
Definition: debug_new.h:147
#define delete2(var)
Definition: delete2.h:25
const bool Equipm_false
Definition: equipm.h:30
bool Equipm
Definition: equipm.h:30
const bool Equipped_false
Definition: equipped.h:30
const bool Equipped_true
Definition: equipped.h:30
bool Favorite
Definition: favorite.h:30
const bool ForceQuantity_false
Definition: forcequantity.h:30
#define _(s)
Definition: gettext.h:35
Gui * gui
Definition: gui.cpp:111
bool Identified
Definition: identified.h:30
const bool IgnoreRecord_false
Definition: ignorerecord.h:30
InventoryWindow * inventoryWindow
uint16_t ItemColor
Definition: itemcolor.h:30
ItemType ::T ItemTypeT
Definition: itemtype.h:43
#define nullptr
Definition: localconsts.h:45
LocalPlayer * localPlayer
const bool LoseFocusOnTab_true
const bool Modal_false
Definition: modal.h:30
ServerTypeT getNetworkType()
Definition: net.cpp:189
Inventory * getInventory()
Definition: playerinfo.cpp:195
int32_t getAttribute(const AttributesT id)
Definition: playerinfo.cpp:102
void setTrading(const Trading trading)
Definition: playerinfo.cpp:396
bool isItemProtected(const int id)
Definition: playerinfo.cpp:515
std::string formatCurrency(const int value)
Definition: unitsdb.cpp:324
Net::TradeHandler * tradeHandler
Definition: net.cpp:98
const bool Opaque_true
Definition: opaque.h:30
PlayerRelationsManager playerRelations
SetupWindow * setupWindow
Definition: setupwindow.cpp:64
const bool ShowEmptyRows_false
Definition: showemptyrows.h:30
std::string strprintf(const char *const format,...)
#define CAPTION_PROPOSE
Definition: tradewindow.cpp:68
#define CAPTION_ACCEPTED
Definition: tradewindow.cpp:74
#define CAPTION_ACCEPT
Definition: tradewindow.cpp:72
TradeWindow * tradeWindow
Definition: tradewindow.cpp:65
#define CAPTION_CONFIRMED
Definition: tradewindow.cpp:70
const bool Trading_false
Definition: trading.h:30
const bool TryRemoveColors_true
const bool Visible_false
Definition: visible.h:30
const bool Visible_true
Definition: visible.h:30