1 /*
2 * The ManaPlus Client
3 * Copyright (C) 2007-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/outfitwindow.h"
25
26 #include "configuration.h"
27 #include "dragdrop.h"
28 #include "game.h"
29
30 #include "being/playerinfo.h"
31
32 #include "const/emoteshortcut.h"
33
34 #include "enums/gui/layouttype.h"
35
36 #include "input/inputactionoperators.h"
37 #include "input/inputmanager.h"
38
39 #include "gui/viewport.h"
40
41 #include "gui/popups/popupmenu.h"
42
43 #include "gui/windows/setupwindow.h"
44
45 #include "gui/widgets/button.h"
46 #include "gui/widgets/checkbox.h"
47 #include "gui/widgets/label.h"
48 #include "gui/widgets/layout.h"
49
50 #include "utils/gettext.h"
51
52 #include "resources/inventory/inventory.h"
53
54 #include <sstream>
55
56 #include "debug.h"
57
58 OutfitWindow *outfitWindow = nullptr;
59
OutfitWindow()60 OutfitWindow::OutfitWindow() :
61 // TRANSLATORS: outfits window name
62 Window(_("Outfits"), Modal_false, nullptr, "outfits.xml"),
63 ActionListener(),
64 // TRANSLATORS: outfits window button
65 mPreviousButton(new Button(this, _("<"), "previous", BUTTON_SKIN, this)),
66 // TRANSLATORS: outfits window button
67 mNextButton(new Button(this, _(">"), "next", BUTTON_SKIN, this)),
68 // TRANSLATORS: outfits window button
69 mEquipBottom(new Button(this, _("Equip"), "equip", BUTTON_SKIN, this)),
70 // TRANSLATORS: outfits window label
71 mCurrentLabel(new Label(this, strprintf(_("Outfit: %d"), 1))),
72 // TRANSLATORS: outfits window checkbox
73 mUnequipCheck(new CheckBox(this, _("Unequip first"),
74 serverConfig.getValueBool("OutfitUnequip0", true),
75 nullptr, std::string())),
76 // TRANSLATORS: outfits window checkbox
77 mAwayOutfitCheck(new CheckBox(this, _("Away outfit"),
78 serverConfig.getValue("OutfitAwayIndex", OUTFITS_COUNT - 1) != 0U,
79 nullptr, std::string())),
80 // TRANSLATORS: outfits window label
81 mKeyLabel(new Label(this, strprintf(_("Key: %s"),
82 keyName(0).c_str()))),
83 mBorderColor(getThemeColor(ThemeColorId::BORDER, 64)),
84 mCurrentOutfit(0),
85 mBoxWidth(33),
86 mBoxHeight(33),
87 mGridWidth(4),
88 mGridHeight(4),
89 mItems(),
90 mAwayOutfit(0),
91 mItemColors(),
92 mItemClicked(false),
93 mItemsUnequip()
94 {
95 setWindowName("Outfits");
96 setResizable(true);
97 setCloseButton(true);
98 setStickyButtonLock(true);
99
100 mBackgroundColor = getThemeColor(ThemeColorId::BACKGROUND, 32);
101
102 setDefaultSize(250, 400, 150, 290);
103 setMinWidth(145);
104 setMinHeight(220);
105
106 if (setupWindow != nullptr)
107 setupWindow->registerWindowForReset(this);
108
109 mCurrentLabel->setAlignment(Graphics::CENTER);
110 mKeyLabel->setAlignment(Graphics::CENTER);
111
112 mUnequipCheck->setActionEventId("unequip");
113 mUnequipCheck->addActionListener(this);
114
115 mAwayOutfitCheck->setActionEventId("away");
116 mAwayOutfitCheck->addActionListener(this);
117
118 place(1, 3, mEquipBottom, 2, 1);
119 place(0, 4, mKeyLabel, 4, 1);
120 place(0, 5, mPreviousButton, 1, 1);
121 place(1, 5, mCurrentLabel, 2, 1);
122 place(3, 5, mNextButton, 1, 1);
123 place(0, 6, mUnequipCheck, 4, 1);
124 place(0, 7, mAwayOutfitCheck, 4, 1);
125
126 Layout &layout = getLayout();
127 layout.setRowHeight(0, LayoutType::SET);
128 layout.setColWidth(4, Layout::CENTER);
129
130 loadWindowState();
131
132 enableVisibleSound(true);
133 load();
134 }
135
~OutfitWindow()136 OutfitWindow::~OutfitWindow()
137 {
138 save();
139 }
140
load()141 void OutfitWindow::load()
142 {
143 const Configuration *cfg = &serverConfig;
144
145 memset(mItems, -1, sizeof(mItems));
146 memset(mItemColors, 1, sizeof(mItemColors));
147
148 for (unsigned o = 0; o < OUTFITS_COUNT; o++)
149 {
150 std::string outfit = cfg->getValue("Outfit" + toString(o), "-1");
151 std::string buf;
152 std::stringstream ss(outfit);
153
154 STD_VECTOR<int> tokens;
155
156 while (ss >> buf)
157 tokens.push_back(atoi(buf.c_str()));
158
159 for (size_t i = 0, sz = tokens.size();
160 i < sz && i < OUTFIT_ITEM_COUNT; i++)
161 {
162 mItems[o][i] = tokens[i];
163 }
164
165 outfit = cfg->getValue("OutfitColor" + toString(o), "1");
166 std::stringstream ss2(outfit);
167
168 tokens.clear();
169
170 STD_VECTOR<unsigned char> tokens2;
171 while (ss2 >> buf)
172 tokens2.push_back(CAST_U8(atoi(buf.c_str())));
173
174 for (size_t i = 0, sz = tokens2.size();
175 i < sz && i < OUTFIT_ITEM_COUNT; i++)
176 {
177 mItemColors[o][i] = fromInt(tokens2[i], ItemColor);
178 }
179
180 mItemsUnequip[o] = cfg->getValueBool("OutfitUnequip" + toString(o),
181 true);
182 }
183 mAwayOutfit = cfg->getValue("OutfitAwayIndex", OUTFITS_COUNT - 1);
184 if (mAwayOutfit >= CAST_S32(OUTFITS_COUNT))
185 mAwayOutfit = CAST_S32(OUTFITS_COUNT) - 1;
186
187 if (mAwayOutfitCheck != nullptr)
188 mAwayOutfitCheck->setSelected(mAwayOutfit == mCurrentOutfit);
189 }
190
save() const191 void OutfitWindow::save() const
192 {
193 std::string outfitStr;
194 std::string outfitColorsStr;
195 for (unsigned o = 0; o < OUTFITS_COUNT; o++)
196 {
197 bool good = false;
198 for (unsigned i = 0; i < OUTFIT_ITEM_COUNT; i++)
199 {
200 const int val = mItems[o][i];
201 const int res = val != 0 ? val : -1;
202 if (res != -1)
203 good = true;
204 outfitStr.append(toString(res));
205 if (i < OUTFIT_ITEM_COUNT - 1)
206 outfitStr.append(" ");
207 outfitColorsStr.append(toString(CAST_S32(
208 toInt(mItemColors[o][i], int))));
209 if (i < OUTFIT_ITEM_COUNT - 1)
210 outfitColorsStr.append(" ");
211 }
212 if (good)
213 {
214 serverConfig.setValue("Outfit" + toString(o), outfitStr);
215 serverConfig.setValue("OutfitColor" + toString(o),
216 outfitColorsStr);
217 }
218 else
219 {
220 serverConfig.deleteKey("Outfit" + toString(o));
221 serverConfig.deleteKey("OutfitColor" + toString(o));
222 }
223
224 if (mItemsUnequip[o])
225 {
226 serverConfig.deleteKey("OutfitUnequip" + toString(o));
227 }
228 else
229 {
230 serverConfig.setValue("OutfitUnequip" + toString(o),
231 mItemsUnequip[o]);
232 }
233 outfitStr.clear();
234 outfitColorsStr.clear();
235 }
236 serverConfig.setValue("OutfitAwayIndex", mAwayOutfit);
237 }
238
action(const ActionEvent & event)239 void OutfitWindow::action(const ActionEvent &event)
240 {
241 const std::string &eventId = event.getId();
242 if (eventId == "next")
243 {
244 next();
245 }
246 else if (eventId == "previous")
247 {
248 previous();
249 }
250 else if (eventId == "unequip")
251 {
252 if (mCurrentOutfit >= 0 && mCurrentOutfit < CAST_S32(
253 OUTFITS_COUNT))
254 {
255 mItemsUnequip[mCurrentOutfit] = mUnequipCheck->isSelected();
256 }
257 }
258 else if (eventId == "equip")
259 {
260 wearOutfit(mCurrentOutfit,
261 true,
262 false);
263 if (Game::instance() != nullptr)
264 Game::instance()->setValidSpeed();
265 }
266 else if (eventId == "away")
267 {
268 mAwayOutfit = mCurrentOutfit;
269 if (!mAwayOutfitCheck->isSelected())
270 mAwayOutfitCheck->setSelected(true);
271 }
272 }
273
wearOutfit(const int outfit,const bool unwearEmpty,const bool select)274 void OutfitWindow::wearOutfit(const int outfit,
275 const bool unwearEmpty,
276 const bool select)
277 {
278 bool isEmpty = true;
279
280 if (outfit < 0 || outfit > CAST_S32(OUTFITS_COUNT))
281 return;
282
283 for (unsigned i = 0; i < OUTFIT_ITEM_COUNT; i++)
284 {
285 const Item *const item = PlayerInfo::getInventory()->findItem(
286 mItems[outfit][i],
287 mItemColors[outfit][i]);
288 if ((item != nullptr)
289 && item->isEquipped() == Equipped_false
290 && (item->getQuantity() != 0))
291 {
292 if (item->isEquipment() == Equipm_true)
293 {
294 PlayerInfo::equipItem(item, Sfx_false);
295 isEmpty = false;
296 }
297 }
298 }
299
300 if ((!isEmpty || unwearEmpty) && outfit < CAST_S32(OUTFITS_COUNT)
301 && mItemsUnequip[outfit])
302 {
303 unequipNotInOutfit(outfit);
304 }
305 if (select)
306 {
307 mCurrentOutfit = outfit;
308 showCurrentOutfit();
309 }
310 }
311
copyOutfit(const int outfit)312 void OutfitWindow::copyOutfit(const int outfit)
313 {
314 copyOutfit(outfit, mCurrentOutfit);
315 }
316
copyOutfit(const int src,const int dst)317 void OutfitWindow::copyOutfit(const int src, const int dst)
318 {
319 if (src < 0 || src > CAST_S32(OUTFITS_COUNT)
320 || dst < 0 || dst > CAST_S32(OUTFITS_COUNT))
321 {
322 return;
323 }
324
325 for (unsigned int i = 0; i < OUTFIT_ITEM_COUNT; i++)
326 mItems[dst][i] = mItems[src][i];
327 save();
328 }
329
draw(Graphics * const graphics)330 void OutfitWindow::draw(Graphics *const graphics)
331 {
332 BLOCK_START("OutfitWindow::draw")
333 Window::draw(graphics);
334
335 if (mCurrentOutfit < 0 || mCurrentOutfit
336 >= static_cast<signed int>(OUTFITS_COUNT))
337 {
338 return;
339 }
340
341 for (unsigned int i = 0; i < OUTFIT_ITEM_COUNT; i++)
342 {
343 const int itemX = mPadding + ((i % mGridWidth) * mBoxWidth);
344 const int itemY = mPadding + mTitleBarHeight
345 + ((i / CAST_U32(mGridWidth)) * mBoxHeight);
346
347 graphics->setColor(mBorderColor);
348 graphics->drawRectangle(Rect(itemX, itemY, 32, 32));
349 graphics->setColor(mBackgroundColor);
350 graphics->fillRectangle(Rect(itemX, itemY, 32, 32));
351
352 if (mItems[mCurrentOutfit][i] < 0)
353 continue;
354
355 bool foundItem = false;
356 const Inventory *const inv = PlayerInfo::getInventory();
357 if (inv != nullptr)
358 {
359 const Item *const item = inv->findItem(mItems[mCurrentOutfit][i],
360 mItemColors[mCurrentOutfit][i]);
361 if (item != nullptr)
362 {
363 // Draw item icon.
364 const Image *const image = item->getImage();
365 if (image != nullptr)
366 {
367 graphics->drawImage(image, itemX, itemY);
368 foundItem = true;
369 }
370 }
371 }
372 if (!foundItem)
373 {
374 Image *const image = Item::getImage(mItems[mCurrentOutfit][i],
375 mItemColors[mCurrentOutfit][i]);
376 if (image != nullptr)
377 {
378 graphics->drawImage(image, itemX, itemY);
379 image->decRef();
380 }
381 }
382 }
383 BLOCK_END("OutfitWindow::draw")
384 }
385
safeDraw(Graphics * const graphics)386 void OutfitWindow::safeDraw(Graphics *const graphics)
387 {
388 BLOCK_START("OutfitWindow::draw")
389 Window::safeDraw(graphics);
390
391 if (mCurrentOutfit < 0 || mCurrentOutfit
392 >= static_cast<signed int>(OUTFITS_COUNT))
393 {
394 return;
395 }
396
397 for (unsigned int i = 0; i < OUTFIT_ITEM_COUNT; i++)
398 {
399 const int itemX = mPadding + ((i % mGridWidth) * mBoxWidth);
400 const int itemY = mPadding + mTitleBarHeight
401 + ((i / CAST_U32(mGridWidth)) * mBoxHeight);
402
403 graphics->setColor(mBorderColor);
404 graphics->drawRectangle(Rect(itemX, itemY, 32, 32));
405 graphics->setColor(mBackgroundColor);
406 graphics->fillRectangle(Rect(itemX, itemY, 32, 32));
407
408 if (mItems[mCurrentOutfit][i] < 0)
409 continue;
410
411 bool foundItem = false;
412 const Inventory *const inv = PlayerInfo::getInventory();
413 if (inv != nullptr)
414 {
415 const Item *const item = inv->findItem(mItems[mCurrentOutfit][i],
416 mItemColors[mCurrentOutfit][i]);
417 if (item != nullptr)
418 {
419 // Draw item icon.
420 const Image *const image = item->getImage();
421 if (image != nullptr)
422 {
423 graphics->drawImage(image, itemX, itemY);
424 foundItem = true;
425 }
426 }
427 }
428 if (!foundItem)
429 {
430 Image *const image = Item::getImage(mItems[mCurrentOutfit][i],
431 mItemColors[mCurrentOutfit][i]);
432 if (image != nullptr)
433 {
434 graphics->drawImage(image, itemX, itemY);
435 image->decRef();
436 }
437 }
438 }
439 BLOCK_END("OutfitWindow::draw")
440 }
441
mouseDragged(MouseEvent & event)442 void OutfitWindow::mouseDragged(MouseEvent &event)
443 {
444 if (event.getButton() == MouseButton::LEFT)
445 {
446 if (dragDrop.isEmpty() && mItemClicked)
447 {
448 if (mCurrentOutfit < 0 || mCurrentOutfit
449 >= static_cast<signed int>(OUTFITS_COUNT))
450 {
451 Window::mouseDragged(event);
452 return;
453 }
454
455 const int index = getIndexFromGrid(event.getX(), event.getY());
456 if (index == -1)
457 {
458 Window::mouseDragged(event);
459 return;
460 }
461 const int itemId = mItems[mCurrentOutfit][index];
462 const ItemColor itemColor = mItemColors[mCurrentOutfit][index];
463 if (itemId < 0)
464 {
465 Window::mouseDragged(event);
466 return;
467 }
468 mMoved = false;
469 event.consume();
470 const Inventory *const inv = PlayerInfo::getInventory();
471 if (inv != nullptr)
472 {
473 Item *const item = inv->findItem(itemId, itemColor);
474 if (item != nullptr)
475 dragDrop.dragItem(item, DragDropSource::Outfit, 0);
476 else
477 dragDrop.clear();
478 mItems[mCurrentOutfit][index] = -1;
479 }
480 }
481 }
482 Window::mouseDragged(event);
483 }
484
mousePressed(MouseEvent & event)485 void OutfitWindow::mousePressed(MouseEvent &event)
486 {
487 const int index = getIndexFromGrid(event.getX(), event.getY());
488 if (event.getButton() == MouseButton::RIGHT && (popupMenu != nullptr))
489 {
490 popupMenu->showOutfitsWindowPopup(viewport->mMouseX,
491 viewport->mMouseY);
492 event.consume();
493 return;
494 }
495 else if (index == -1)
496 {
497 Window::mousePressed(event);
498 return;
499 }
500 mMoved = false;
501 event.consume();
502
503 if (mItems[mCurrentOutfit][index] > 0)
504 {
505 mItemClicked = true;
506 }
507 else
508 {
509 if (dragDrop.isSelected())
510 {
511 mItems[mCurrentOutfit][index] = dragDrop.getSelected();
512 mItemColors[mCurrentOutfit][index] = dragDrop.getSelectedColor();
513 dragDrop.deselect();
514 save();
515 }
516 }
517
518 Window::mousePressed(event);
519 }
520
mouseReleased(MouseEvent & event)521 void OutfitWindow::mouseReleased(MouseEvent &event)
522 {
523 if (event.getButton() == MouseButton::LEFT)
524 {
525 if (mCurrentOutfit < 0 || mCurrentOutfit
526 >= static_cast<signed int>(OUTFITS_COUNT))
527 {
528 return;
529 }
530 const int index = getIndexFromGrid(event.getX(), event.getY());
531 if (index == -1)
532 {
533 dragDrop.clear();
534 Window::mouseReleased(event);
535 return;
536 }
537 mMoved = false;
538 event.consume();
539 if (!dragDrop.isEmpty())
540 {
541 if (dragDrop.isSourceItemContainer())
542 {
543 mItems[mCurrentOutfit][index] = dragDrop.getItem();
544 mItemColors[mCurrentOutfit][index] = dragDrop.getItemColor();
545 dragDrop.clear();
546 dragDrop.deselect();
547 save();
548 }
549 }
550 if (mItemClicked)
551 mItemClicked = false;
552 }
553 Window::mouseReleased(event);
554 }
555
getIndexFromGrid(const int pointX,const int pointY) const556 int OutfitWindow::getIndexFromGrid(const int pointX, const int pointY) const
557 {
558 const Rect tRect = Rect(mPadding, mTitleBarHeight,
559 mGridWidth * mBoxWidth, mGridHeight * mBoxHeight);
560 if (!tRect.isPointInRect(pointX, pointY))
561 return -1;
562 const int index = (((pointY - mTitleBarHeight) / mBoxHeight) * mGridWidth)
563 + (pointX - mPadding) / mBoxWidth;
564 if (index >= CAST_S32(OUTFIT_ITEM_COUNT) || index < 0)
565 return -1;
566 return index;
567 }
568
unequipNotInOutfit(const int outfit) const569 void OutfitWindow::unequipNotInOutfit(const int outfit) const
570 {
571 // here we think that outfit is correct index
572
573 const Inventory *const inventory = PlayerInfo::getInventory();
574 if (inventory == nullptr)
575 return;
576
577 const unsigned int invSize = inventory->getSize();
578 for (unsigned i = 0; i < invSize; i++)
579 {
580 const Item *const item = inventory->getItem(i);
581 if ((item != nullptr) && item->isEquipped() == Equipped_true)
582 {
583 bool found = false;
584 for (unsigned f = 0; f < OUTFIT_ITEM_COUNT; f++)
585 {
586 if (item->getId() == mItems[outfit][f])
587 {
588 found = true;
589 break;
590 }
591 }
592 if (!found)
593 PlayerInfo::unequipItem(item, Sfx_false);
594 }
595 }
596 }
597
keyName(const int number)598 std::string OutfitWindow::keyName(const int number)
599 {
600 if (number < 0 || number >= SHORTCUT_EMOTES)
601 return "";
602 return inputManager.getKeyStringLong(InputAction::OUTFIT_1 + number);
603 }
604
next()605 void OutfitWindow::next()
606 {
607 if (mCurrentOutfit < (CAST_S32(OUTFITS_COUNT) - 1))
608 mCurrentOutfit++;
609 else
610 mCurrentOutfit = 0;
611 showCurrentOutfit();
612 }
613
previous()614 void OutfitWindow::previous()
615 {
616 if (mCurrentOutfit > 0)
617 mCurrentOutfit--;
618 else
619 mCurrentOutfit = OUTFITS_COUNT - 1;
620 showCurrentOutfit();
621 }
622
showCurrentOutfit()623 void OutfitWindow::showCurrentOutfit()
624 {
625 // TRANSLATORS: outfits window label
626 mCurrentLabel->setCaption(strprintf(_("Outfit: %d"), mCurrentOutfit + 1));
627 if (mCurrentOutfit < CAST_S32(OUTFITS_COUNT))
628 mUnequipCheck->setSelected(mItemsUnequip[mCurrentOutfit]);
629 else
630 mUnequipCheck->setSelected(false);
631 // TRANSLATORS: outfits window label
632 mKeyLabel->setCaption(strprintf(_("Key: %s"),
633 keyName(mCurrentOutfit).c_str()));
634 mAwayOutfitCheck->setSelected(mAwayOutfit == mCurrentOutfit);
635 }
636
wearNextOutfit(const bool all)637 void OutfitWindow::wearNextOutfit(const bool all)
638 {
639 next();
640 if (!all && mCurrentOutfit >= 0 && mCurrentOutfit
641 < CAST_S32(OUTFITS_COUNT))
642 {
643 bool fromStart = false;
644 while (!mItemsUnequip[mCurrentOutfit])
645 {
646 next();
647 if (mCurrentOutfit == 0)
648 {
649 if (!fromStart)
650 fromStart = true;
651 else
652 return;
653 }
654 }
655 }
656 wearOutfit(mCurrentOutfit,
657 true,
658 false);
659 }
660
wearPreviousOutfit(const bool all)661 void OutfitWindow::wearPreviousOutfit(const bool all)
662 {
663 previous();
664 if (!all && mCurrentOutfit >= 0 && mCurrentOutfit
665 < CAST_S32(OUTFITS_COUNT))
666 {
667 bool fromStart = false;
668 while (!mItemsUnequip[mCurrentOutfit])
669 {
670 previous();
671 if (mCurrentOutfit == 0)
672 {
673 if (!fromStart)
674 fromStart = true;
675 else
676 return;
677 }
678 }
679 }
680 wearOutfit(mCurrentOutfit,
681 true,
682 false);
683 }
684
copyFromEquiped()685 void OutfitWindow::copyFromEquiped()
686 {
687 copyFromEquiped(mCurrentOutfit);
688 }
689
copyFromEquiped(const int dst)690 void OutfitWindow::copyFromEquiped(const int dst)
691 {
692 const Inventory *const inventory = PlayerInfo::getInventory();
693 if (inventory == nullptr)
694 return;
695
696 int outfitCell = 0;
697 for (unsigned i = 0, sz = inventory->getSize(); i < sz; i++)
698 {
699 const Item *const item = inventory->getItem(i);
700 if ((item != nullptr) && item->isEquipped() == Equipped_true)
701 {
702 mItems[dst][outfitCell] = item->getId();
703 mItemColors[dst][outfitCell++] = item->getColor();
704 if (outfitCell >= CAST_S32(OUTFIT_ITEM_COUNT))
705 break;
706 }
707 }
708 save();
709 }
710
wearAwayOutfit()711 void OutfitWindow::wearAwayOutfit()
712 {
713 copyFromEquiped(OUTFITS_COUNT);
714 wearOutfit(mAwayOutfit,
715 false,
716 false);
717 }
718
unwearAwayOutfit()719 void OutfitWindow::unwearAwayOutfit()
720 {
721 wearOutfit(OUTFITS_COUNT,
722 true,
723 false);
724 }
725
clearCurrentOutfit()726 void OutfitWindow::clearCurrentOutfit()
727 {
728 if (mCurrentOutfit < 0 || mCurrentOutfit
729 >= static_cast<signed int>(OUTFITS_COUNT))
730 {
731 return;
732 }
733 for (unsigned f = 0; f < OUTFIT_ITEM_COUNT; f++)
734 {
735 mItems[mCurrentOutfit][f] = -1;
736 mItemColors[mCurrentOutfit][f] = ItemColor_one;
737 }
738 save();
739 }
740
getOutfitString() const741 std::string OutfitWindow::getOutfitString() const
742 {
743 std::string str;
744 for (unsigned int i = 0; i < OUTFIT_ITEM_COUNT; i++)
745 {
746 const int id = mItems[mCurrentOutfit][i];
747 if (id < 0)
748 continue;
749
750 const ItemColor color = mItemColors[mCurrentOutfit][i];
751 STD_VECTOR<int> ids;
752 ids.push_back(id);
753 ids.push_back(CAST_S32(color));
754
755 const std::string name = ItemDB::getNamesStr(ids);
756 if (name.empty())
757 continue;
758 str.append("[");
759 str.append(name);
760 str.append("] ");
761 }
762 return str;
763 }
764