GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/iteminfo.cpp Lines: 84 197 42.6 %
Date: 2017-11-29 Branches: 31 142 21.8 %

Line Branch Exec Source
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-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "resources/iteminfo.h"
24
25
#include "const/resources/spriteaction.h"
26
27
#include "const/resources/map/map.h"
28
29
#include "enums/resources/spritedirection.h"
30
31
#include "resources/itemmenuitem.h"
32
33
#include "resources/db/colordb.h"
34
#include "resources/db/itemdb.h"
35
36
#include "utils/checkutils.h"
37
#include "utils/dtor.h"
38
#include "utils/stringutils.h"
39
40
#include "debug.h"
41
42
254
ItemInfo::ItemInfo() :
43
    mDisplay(),
44
    mMissile(),
45
    mName(),
46
    mNameEn(),
47
    mDescription(),
48
    mEffect(),
49
    mUseButton(),
50
    mUseButton2(),
51
    mType(ItemDbType::UNUSABLE),
52
    mWeight(0),
53
    mView(0),
54
    mId(0),
55
    mIsRemoveSprites(false),
56
    mSpriteToItemReplaceList(),
57
    mAttackAction(SpriteAction::INVALID),
58
    mSkyAttackAction(SpriteAction::INVALID),
59
    mWaterAttackAction(SpriteAction::INVALID),
60
    mRideAttackAction(SpriteAction::INVALID),
61
    mAttackRange(0),
62
    mMissileParticle(),
63
    mAnimationFiles(),
64
    mSounds(),
65
    mTags(),
66
    mColorsList(nullptr),
67
    mIconColorsList(nullptr),
68
    mInventoryMenu(),
69
    mStorageMenu(),
70
    mCartMenu(),
71
    mColorsListName(),
72
    mIconColorsListName(),
73
    mCardColor(ItemColor_zero),
74
    mHitEffectId(-1),
75
    mCriticalHitEffectId(-1),
76
    mMissEffectId(-1),
77
    maxFloorOffsetX(mapTileSize),
78
    maxFloorOffsetY(mapTileSize),
79
    mPickupCursor(Cursor::CURSOR_POINTER),
80
5842
    mProtected(false)
81
{
82
2794
    for (int f = 0; f < 10; f ++)
83
    {
84
2540
        mSpriteToItemReplaceMap[f] = nullptr;
85
2540
        mDrawBefore[f] = -1;
86
2540
        mDrawAfter[f] = -1;
87
2540
        mDrawPriority[f] = 0;
88
    }
89
254
}
90
91
5080
ItemInfo::~ItemInfo()
92
{
93
508
    delete_all(mSpriteToItemReplaceList);
94
508
    mSpriteToItemReplaceList.clear();
95
2794
    for (int f = 0; f < 10; f ++)
96
2540
        mSpriteToItemReplaceMap[f] = nullptr;
97
254
}
98
99
210
const std::string &ItemInfo::getSprite(const GenderT gender,
100
                                       const BeingTypeId race) const
101
{
102
210
    if (mView != 0)
103
    {
104
        // Forward the request to the item defining how to view this item
105
        return ItemDB::get(mView).getSprite(gender, race);
106
    }
107

212
    static const std::string empty;
108
    std::map<int, std::string>::const_iterator i =
109
210
        mAnimationFiles.find(CAST_S32(gender) +
110
420
        toInt(race, int) * 4);
111
112
420
    if (i != mAnimationFiles.end())
113
210
        return i->second;
114
    i = mAnimationFiles.find(CAST_S32(gender));
115
    if (i != mAnimationFiles.end())
116
        return i->second;
117
    return empty;
118
}
119
120
228
void ItemInfo::setAttackAction(const std::string &attackAction)
121
{
122
228
    if (attackAction.empty())
123
228
        mAttackAction = SpriteAction::ATTACK;  // (Equal to unarmed animation)
124
    else
125
        mAttackAction = attackAction;
126
228
}
127
128
228
void ItemInfo::setSkyAttackAction(const std::string &attackAction)
129
{
130
228
    if (attackAction.empty())
131
228
        mSkyAttackAction = SpriteAction::ATTACKSKY;
132
    else
133
        mSkyAttackAction = attackAction;
134
228
}
135
136
228
void ItemInfo::setWaterAttackAction(const std::string &attackAction)
137
{
138
228
    if (attackAction.empty())
139
228
        mWaterAttackAction = SpriteAction::ATTACKWATER;
140
    else
141
        mWaterAttackAction = attackAction;
142
228
}
143
144
228
void ItemInfo::setRideAttackAction(const std::string &attackAction)
145
{
146
228
    if (attackAction.empty())
147
228
        mRideAttackAction = SpriteAction::ATTACKRIDE;
148
    else
149
        mRideAttackAction = attackAction;
150
228
}
151
152
96
void ItemInfo::addSound(const ItemSoundEvent::Type event,
153
                        const std::string &filename, const int delay)
154
{
155
384
    mSounds[event].push_back(SoundInfo(
156
        filename,
157
        delay));
158
96
}
159
160
const SoundInfo &ItemInfo::getSound(const ItemSoundEvent::Type event) const
161
{
162
    static const SoundInfo empty("", 0);
163
    std::map<ItemSoundEvent::Type, SoundInfoVect>::const_iterator i;
164
165
    i = mSounds.find(event);
166
167
    if (i == mSounds.end())
168
        return empty;
169
    return (!i->second.empty()) ? i->second[CAST_U32(rand())
170
        % i->second.size()] : empty;
171
}
172
173
IntMap *ItemInfo::addReplaceSprite(const int sprite,
174
                                   const int direction)
175
{
176
    if (direction < 0 || direction >= 10)
177
        return nullptr;
178
179
    SpriteToItemMap *spMap = mSpriteToItemReplaceMap[direction];
180
181
    if (spMap == nullptr)
182
    {
183
        spMap = new SpriteToItemMap;
184
        mSpriteToItemReplaceMap[direction] = spMap;
185
        mSpriteToItemReplaceList.push_back(spMap);
186
    }
187
188
    SpriteToItemMap::iterator it = spMap->find(sprite);
189
    if (it == spMap->end())
190
    {
191
        IntMap tmp;
192
        (*mSpriteToItemReplaceMap[direction])[sprite] = tmp;
193
        it = mSpriteToItemReplaceMap[direction]->find(sprite);
194
    }
195
    return &it->second;
196
}
197
198
228
void ItemInfo::setColorsList(const std::string &name)
199
{
200
228
    if (name.empty())
201
    {
202
60
        mColorsList = nullptr;
203
60
        mColorsListName.clear();
204
    }
205
    else
206
    {
207
168
        mColorsList = ColorDB::getColorsList(name);
208
168
        mColorsListName = name;
209
    }
210
228
}
211
212
228
void ItemInfo::setIconColorsList(const std::string &name)
213
{
214
228
    if (name.empty())
215
    {
216
60
        mIconColorsList = nullptr;
217
60
        mIconColorsListName.clear();
218
    }
219
    else
220
    {
221
168
        mIconColorsList = ColorDB::getColorsList(name);
222
168
        mIconColorsListName = name;
223
    }
224
228
}
225
226
std::string ItemInfo::getDyeColorsString(const ItemColor color) const
227
{
228
    if ((mColorsList == nullptr) || mColorsListName.empty())
229
        return "";
230
231
    const std::map <ItemColor, ItemColorData>::const_iterator
232
        it = mColorsList->find(color);
233
    if (it == mColorsList->end())
234
        return "";
235
236
    return it->second.color;
237
}
238
239
4
std::string ItemInfo::getDyeIconColorsString(const ItemColor color) const
240
{
241

4
    if ((mIconColorsList == nullptr) || mIconColorsListName.empty())
242
12
        return "";
243
244
    const std::map <ItemColor, ItemColorData>::const_iterator
245
        it = mIconColorsList->find(color);
246
    if (it == mIconColorsList->end())
247
        return "";
248
249
    return it->second.color;
250
}
251
252
const std::string ItemInfo::getDescription(const ItemColor color) const
253
{
254
    return replaceColors(mDescription, color);
255
}
256
257
2
const std::string ItemInfo::getName(const ItemColor color) const
258
{
259
6
    return replaceColors(mName, color);
260
}
261
262
const std::string ItemInfo::getNameEn(const ItemColor color) const
263
{
264
    return replaceColors(mNameEn, color);
265
}
266
267
2
const std::string ItemInfo::replaceColors(std::string str,
268
                                          const ItemColor color) const
269
{
270
4
    std::string name;
271

2
    if ((mColorsList != nullptr) && !mColorsListName.empty())
272
    {
273
        const std::map <ItemColor, ItemColorData>::const_iterator
274
            it = mColorsList->find(color);
275
        if (it == mColorsList->end())
276
            name = "unknown";
277
        else
278
            name = it->second.name;
279
    }
280
    else
281
    {
282
        name = "unknown";
283
    }
284
285

10
    str = replaceAll(str, "%color%", name);
286
2
    if (!name.empty())
287
4
        name[0] = CAST_S8(toupper(name[0]));
288
289

12
    return replaceAll(str, "%Color%", name);
290
}
291
292
const SpriteToItemMap *ItemInfo::getSpriteToItemReplaceMap(const int direction)
293
                                                           const
294
{
295
    if (direction < 0 || direction >= 10)
296
        return nullptr;
297
298
    const SpriteToItemMap *const spMap = mSpriteToItemReplaceMap[direction];
299
    if (spMap != nullptr)
300
        return spMap;
301
    if (direction == SpriteDirection::UPLEFT
302
        || direction == SpriteDirection::UPRIGHT)
303
    {
304
        return mSpriteToItemReplaceMap[SpriteDirection::UP];
305
    }
306
307
    if (direction == SpriteDirection::DOWNLEFT
308
        || direction == SpriteDirection::DOWNRIGHT)
309
    {
310
        return mSpriteToItemReplaceMap[SpriteDirection::DOWN];
311
    }
312
313
    return nullptr;
314
}
315
316
684
void ItemInfo::setSpriteOrder(int *const ptr,
317
                              const int direction,
318
                              const int n,
319
                              const int def)
320
{
321

684
    switch (direction)
322
    {
323
        case -1:
324
        {
325
14364
            for (int f = 0; f < 10; f ++)
326
            {
327
6840
                if (ptr[f] == def)
328
6840
                    ptr[f] = n;
329
            }
330
            return;
331
        }
332
        case -2:
333
        {
334
            ptr[SpriteDirection::DOWN] = n;
335
            ptr[SpriteDirection::DOWNLEFT] = n;
336
            ptr[SpriteDirection::DOWNRIGHT] = n;
337
            return;
338
        }
339
        case -3:
340
        {
341
            ptr[SpriteDirection::UP] = n;
342
            ptr[SpriteDirection::UPLEFT] = n;
343
            ptr[SpriteDirection::UPRIGHT] = n;
344
            return;
345
        }
346
        default:
347
            break;
348
    }
349
    if (direction < 0 || direction >= 9)
350
        return;
351
352
    if (direction == SpriteDirection::UP)
353
    {
354
        if (ptr[SpriteDirection::UPLEFT] == def)
355
            ptr[SpriteDirection::UPLEFT] = n;
356
        if (ptr[SpriteDirection::UPRIGHT] == def)
357
            ptr[SpriteDirection::UPRIGHT] = n;
358
    }
359
    else if (direction == SpriteDirection::DOWN)
360
    {
361
        if (ptr[SpriteDirection::DOWNLEFT] == def)
362
            ptr[SpriteDirection::DOWNLEFT] = n;
363
        if (ptr[SpriteDirection::DOWNRIGHT] == def)
364
            ptr[SpriteDirection::DOWNRIGHT] = n;
365
    }
366
    ptr[direction] = n;
367
}
368
369
228
void ItemInfo::setDrawBefore(const int direction, const int n)
370
{
371
228
    setSpriteOrder(&mDrawBefore[0], direction, n);
372
228
}
373
374
228
void ItemInfo::setDrawAfter(const int direction, const int n)
375
{
376
228
    setSpriteOrder(&mDrawAfter[0], direction, n);
377
228
}
378
379
228
void ItemInfo::setDrawPriority(const int direction, const int n)
380
{
381
228
    setSpriteOrder(&mDrawPriority[0], direction, n, 0);
382
228
}
383
384
int ItemInfo::getDrawBefore(const int direction) const
385
{
386
    if (direction < 0 || direction >= 10)
387
        return -1;
388
    return mDrawBefore[direction];
389
}
390
391
int ItemInfo::getDrawAfter(const int direction) const
392
{
393
    if (direction < 0 || direction >= 10)
394
        return -1;
395
    return mDrawAfter[direction];
396
}
397
398
int ItemInfo::getDrawPriority(const int direction) const
399
{
400
    if (direction < 0 || direction >= 10)
401
        return 0;
402
    return mDrawPriority[direction];
403
}
404
405
708
void ItemInfo::setSprite(const std::string &animationFile,
406
                         const GenderT gender,
407
                         const int race)
408
{
409
1416
    mAnimationFiles[CAST_S32(gender) + race * 4] = animationFile;
410
708
}
411
412
std::string ItemInfo::getColorName(const ItemColor idx) const
413
{
414
    if (mColorsList == nullptr)
415
        return std::string();
416
417
    const std::map <ItemColor, ItemColorData>::const_iterator
418
        it = mColorsList->find(idx);
419
    if (it == mColorsList->end())
420
    {
421
        reportAlways("Color %d for palette %s not found",
422
            CAST_S32(idx),
423
            mColorsListName.c_str());
424
        return std::string();
425
    }
426
    return it->second.name;
427
}
428
429
std::string ItemInfo::getColor(const ItemColor idx) const
430
{
431
    if (mColorsList == nullptr)
432
        return std::string();
433
434
    const std::map <ItemColor, ItemColorData>::const_iterator
435
        it = mColorsList->find(idx);
436
    if (it == mColorsList->end())
437
    {
438
        reportAlways("Color %d for palette %s not found",
439
            CAST_S32(idx),
440
            mColorsListName.c_str());
441
        return std::string();
442
    }
443
    return it->second.color;
444
}
445
446
std::string ItemInfo::getIconColorName(const ItemColor idx) const
447
{
448
    if (mIconColorsList == nullptr)
449
        return std::string();
450
451
    const std::map <ItemColor, ItemColorData>::const_iterator
452
        it = mIconColorsList->find(idx);
453
    if (it == mIconColorsList->end())
454
    {
455
        reportAlways("Color %d for palette %s not found",
456
            CAST_S32(idx),
457
            mColorsListName.c_str());
458
        return std::string();
459
    }
460
    return it->second.name;
461
}
462
463
std::string ItemInfo::getIconColor(const ItemColor idx) const
464
{
465
    if (mIconColorsList == nullptr)
466
        return std::string();
467
468
    const std::map <ItemColor, ItemColorData>::const_iterator
469
        it = mIconColorsList->find(idx);
470
    if (it == mIconColorsList->end())
471
    {
472
        reportAlways("Color %d for palette %s not found",
473
            CAST_S32(idx),
474
            mColorsListName.c_str());
475
        return std::string();
476
    }
477
    return it->second.color;
478
}
479
480
const std::string ItemInfo::getLink() const
481
{
482
    return strprintf("[@@%d|%[email protected]@]", mId, mName.c_str());
483

6
}