GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/gui/windows/outfitwindow.cpp Lines: 105 372 28.2 %
Date: 2021-03-17 Branches: 122 450 27.1 %

Line Branch Exec Source
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
60
1
OutfitWindow::OutfitWindow() :
61
    // TRANSLATORS: outfits window name
62
1
    Window(_("Outfits"), Modal_false, nullptr, "outfits.xml"),
63
    ActionListener(),
64
    // TRANSLATORS: outfits window button
65

2
    mPreviousButton(new Button(this, _("<"), "previous", BUTTON_SKIN, this)),
66
    // TRANSLATORS: outfits window button
67

2
    mNextButton(new Button(this, _(">"), "next", BUTTON_SKIN, this)),
68
    // TRANSLATORS: outfits window button
69

2
    mEquipBottom(new Button(this, _("Equip"), "equip", BUTTON_SKIN, this)),
70
    // TRANSLATORS: outfits window label
71

2
    mCurrentLabel(new Label(this, strprintf(_("Outfit: %d"), 1))),
72
    // TRANSLATORS: outfits window checkbox
73
1
    mUnequipCheck(new CheckBox(this, _("Unequip first"),
74

4
        serverConfig.getValueBool("OutfitUnequip0", true),
75

2
        nullptr, std::string())),
76
    // TRANSLATORS: outfits window checkbox
77
1
    mAwayOutfitCheck(new CheckBox(this, _("Away outfit"),
78

4
        serverConfig.getValue("OutfitAwayIndex", OUTFITS_COUNT - 1) != 0U,
79

2
        nullptr, std::string())),
80
    // TRANSLATORS: outfits window label
81
2
    mKeyLabel(new Label(this, strprintf(_("Key: %s"),
82

3
        keyName(0).c_str()))),
83
2
    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







39
    mItemsUnequip()
94
{
95
4
    setWindowName("Outfits");
96
1
    setResizable(true);
97
1
    setCloseButton(true);
98
1
    setStickyButtonLock(true);
99
100
2
    mBackgroundColor = getThemeColor(ThemeColorId::BACKGROUND, 32);
101
102
1
    setDefaultSize(250, 400, 150, 290);
103
1
    setMinWidth(145);
104
1
    setMinHeight(220);
105
106
1
    if (setupWindow != nullptr)
107
        setupWindow->registerWindowForReset(this);
108
109
2
    mCurrentLabel->setAlignment(Graphics::CENTER);
110
2
    mKeyLabel->setAlignment(Graphics::CENTER);
111
112
4
    mUnequipCheck->setActionEventId("unequip");
113
1
    mUnequipCheck->addActionListener(this);
114
115
4
    mAwayOutfitCheck->setActionEventId("away");
116
1
    mAwayOutfitCheck->addActionListener(this);
117
118
1
    place(1, 3, mEquipBottom, 2, 1);
119
1
    place(0, 4, mKeyLabel, 4, 1);
120
1
    place(0, 5, mPreviousButton, 1, 1);
121
1
    place(1, 5, mCurrentLabel, 2, 1);
122
1
    place(3, 5, mNextButton, 1, 1);
123
1
    place(0, 6, mUnequipCheck, 4, 1);
124
1
    place(0, 7, mAwayOutfitCheck, 4, 1);
125
126
1
    Layout &layout = getLayout();
127
1
    layout.setRowHeight(0, LayoutType::SET);
128
1
    layout.setColWidth(4, Layout::CENTER);
129
130
1
    loadWindowState();
131
132
2
    enableVisibleSound(true);
133
1
    load();
134
1
}
135
136
4
OutfitWindow::~OutfitWindow()
137
{
138
1
    save();
139
2
}
140
141
1
void OutfitWindow::load()
142
{
143
1
    const Configuration *cfg = &serverConfig;
144
145
2
    memset(mItems, -1, sizeof(mItems));
146
2
    memset(mItemColors, 1, sizeof(mItemColors));
147
148
101
    for (unsigned o = 0; o < OUTFITS_COUNT; o++)
149
    {
150

700
        std::string outfit = cfg->getValue("Outfit" + toString(o), "-1");
151
200
        std::string buf;
152
200
        std::stringstream ss(outfit);
153
154
100
        STD_VECTOR<int> tokens;
155
156

500
        while (ss >> buf)
157
300
            tokens.push_back(atoi(buf.c_str()));
158
159
300
        for (size_t i = 0, sz = tokens.size();
160
200
             i < sz && i < OUTFIT_ITEM_COUNT; i++)
161
        {
162
200
            mItems[o][i] = tokens[i];
163
        }
164
165


600
        outfit = cfg->getValue("OutfitColor" + toString(o), "1");
166
200
        std::stringstream ss2(outfit);
167
168
100
        tokens.clear();
169
170
100
        STD_VECTOR<unsigned char> tokens2;
171

500
        while (ss2 >> buf)
172
300
            tokens2.push_back(CAST_U8(atoi(buf.c_str())));
173
174
300
        for (size_t i = 0, sz = tokens2.size();
175
200
             i < sz && i < OUTFIT_ITEM_COUNT; i++)
176
        {
177
200
            mItemColors[o][i] = fromInt(tokens2[i], ItemColor);
178
        }
179
180

300
        mItemsUnequip[o] = cfg->getValueBool("OutfitUnequip" + toString(o),
181
                                             true);
182
    }
183
3
    mAwayOutfit = cfg->getValue("OutfitAwayIndex", OUTFITS_COUNT - 1);
184
1
    if (mAwayOutfit >= CAST_S32(OUTFITS_COUNT))
185
        mAwayOutfit = CAST_S32(OUTFITS_COUNT) - 1;
186
187
1
    if (mAwayOutfitCheck != nullptr)
188
1
        mAwayOutfitCheck->setSelected(mAwayOutfit == mCurrentOutfit);
189
1
}
190
191
1
void OutfitWindow::save() const
192
{
193
2
    std::string outfitStr;
194
2
    std::string outfitColorsStr;
195
101
    for (unsigned o = 0; o < OUTFITS_COUNT; o++)
196
    {
197
        bool good = false;
198
3300
        for (unsigned i = 0; i < OUTFIT_ITEM_COUNT; i++)
199
        {
200
1600
            const int val = mItems[o][i];
201
1600
            const int res = val != 0 ? val : -1;
202
1600
            if (res != -1)
203
                good = true;
204
4800
            outfitStr.append(toString(res));
205
1600
            if (i < OUTFIT_ITEM_COUNT - 1)
206
1500
                outfitStr.append(" ");
207
3200
            outfitColorsStr.append(toString(CAST_S32(
208
3200
                toInt(mItemColors[o][i], int))));
209
1600
            if (i < OUTFIT_ITEM_COUNT - 1)
210
1500
                outfitColorsStr.append(" ");
211
        }
212
100
        if (good)
213
        {
214
            serverConfig.setValue("Outfit" + toString(o), outfitStr);
215
            serverConfig.setValue("OutfitColor" + toString(o),
216
                outfitColorsStr);
217
        }
218
        else
219
        {
220

300
            serverConfig.deleteKey("Outfit" + toString(o));
221

300
            serverConfig.deleteKey("OutfitColor" + toString(o));
222
        }
223
224
100
        if (mItemsUnequip[o])
225
        {
226

300
            serverConfig.deleteKey("OutfitUnequip" + toString(o));
227
        }
228
        else
229
        {
230
            serverConfig.setValue("OutfitUnequip" + toString(o),
231
                mItemsUnequip[o]);
232
        }
233
100
        outfitStr.clear();
234
100
        outfitColorsStr.clear();
235
    }
236

4
    serverConfig.setValue("OutfitAwayIndex", mAwayOutfit);
237
1
}
238
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
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
312
void OutfitWindow::copyOutfit(const int outfit)
313
{
314
    copyOutfit(outfit, mCurrentOutfit);
315
}
316
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
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
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
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
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
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
556
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
569
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
598
1
std::string OutfitWindow::keyName(const int number)
599
{
600
1
    if (number < 0 || number >= SHORTCUT_EMOTES)
601
        return "";
602
1
    return inputManager.getKeyStringLong(InputAction::OUTFIT_1 + number);
603
}
604
605
void OutfitWindow::next()
606
{
607
    if (mCurrentOutfit < (CAST_S32(OUTFITS_COUNT) - 1))
608
        mCurrentOutfit++;
609
    else
610
        mCurrentOutfit = 0;
611
    showCurrentOutfit();
612
}
613
614
void OutfitWindow::previous()
615
{
616
    if (mCurrentOutfit > 0)
617
        mCurrentOutfit--;
618
    else
619
        mCurrentOutfit = OUTFITS_COUNT - 1;
620
    showCurrentOutfit();
621
}
622
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
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
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
685
void OutfitWindow::copyFromEquiped()
686
{
687
    copyFromEquiped(mCurrentOutfit);
688
}
689
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
711
void OutfitWindow::wearAwayOutfit()
712
{
713
    copyFromEquiped(OUTFITS_COUNT);
714
    wearOutfit(mAwayOutfit,
715
        false,
716
        false);
717
}
718
719
void OutfitWindow::unwearAwayOutfit()
720
{
721
    wearOutfit(OUTFITS_COUNT,
722
        true,
723
        false);
724
}
725
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
741
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

3
}