GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/being/playerinfo.cpp Lines: 37 279 13.3 %
Date: 2018-11-12 Branches: 10 210 4.8 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2010  The Mana Developers
4
 *  Copyright (C) 2011-2018  The ManaPlus Developers
5
 *
6
 *  This file is part of The ManaPlus Client.
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 2 of the License, or
11
 *  any later version.
12
 *
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU General Public License
19
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#include "being/playerinfo.h"
23
24
#include "configuration.h"
25
#include "itemsoundmanager.h"
26
27
#include "being/localplayer.h"
28
29
#include "being/homunculusinfo.h"
30
#include "being/mercenaryinfo.h"
31
#include "being/petinfo.h"
32
33
#include "gui/windows/inventorywindow.h"
34
#include "gui/windows/npcdialog.h"
35
36
#include "listeners/statlistener.h"
37
38
#include "net/homunculushandler.h"
39
#include "net/inventoryhandler.h"
40
#include "net/mercenaryhandler.h"
41
#include "net/playerhandler.h"
42
43
#include "resources/item/item.h"
44
45
#include "utils/delete2.h"
46
47
#include "utils/translation/translationmanager.h"
48
49
#include "debug.h"
50
51
namespace PlayerInfo
52
{
53
54
1
PlayerInfoBackend mData;
55
int mCharId = 0;
56
57
Inventory *mInventory = nullptr;
58
Inventory *mCartInventory = nullptr;
59
MercenaryInfo *mMercenary = nullptr;
60
HomunculusInfo *mHomunculus = nullptr;
61
PetInfo *mPet = nullptr;
62
1
std::string mRoomName;
63
Equipment *mEquipment = nullptr;
64
BeingId mPetBeingId = BeingId_zero;
65
GuildPositionFlags::Type mGuildPositionFlags = GuildPositionFlags::None;
66
BeingId mElementalId = BeingId_zero;
67
68
Trading mTrading = Trading_false;
69
bool mVending = false;
70
int mLevelProgress = 0;
71
int mServerLanguage = -1;
72
1
std::set<int> mProtectedItems;
73
74
// --- Triggers ---------------------------------------------------------------
75
76
void triggerAttr(const AttributesT id,
77
                 const int64_t old)
78
{
79
    AttributeListener::distributeEvent(id, old,
80
        mData.mAttributes.find(id)->second);
81
}
82
83
void triggerStat(const AttributesT id,
84
                 const int old1,
85
                 const int old2)
86
{
87
188
    StatListener::distributeEvent(id, old1, old2);
88
}
89
90
// --- Attributes -------------------------------------------------------------
91
92
3
int64_t getAttribute64(const AttributesT id)
93
{
94
6
    const AtrIntMap::const_iterator it = mData.mAttributes.find(id);
95
3
    if (it != mData.mAttributes.end())
96
        return it->second;
97
    return 0;
98
}
99
100
22
int32_t getAttribute(const AttributesT id)
101
{
102
44
    const AtrIntMap::const_iterator it = mData.mAttributes.find(id);
103
22
    if (it != mData.mAttributes.end())
104
        return CAST_S32(it->second);
105
    return 0;
106
}
107
108
void setAttribute(const AttributesT id,
109
                  const int64_t value,
110
                  const Notify notify)
111
{
112
    const int64_t old = mData.mAttributes[id];
113
    mData.mAttributes[id] = value;
114
    if (notify == Notify_true)
115
        triggerAttr(id, old);
116
}
117
118
int getSkillLevel(const int id)
119
{
120
    const IntMap::const_iterator it = mData.mSkills.find(id);
121
    if (it != mData.mSkills.end())
122
        return it->second;
123
    return 0;
124
}
125
126
void setSkillLevel(const int id, const int value)
127
{
128
    mData.mSkills[id] = value;
129
}
130
131
// --- Stats ------------------------------------------------------------------
132
133
int getStatBase(const AttributesT id)
134
{
135
    const StatMap::const_iterator it = mData.mStats.find(id);
136
    if (it != mData.mStats.end())
137
        return it->second.base;
138
    return 0;
139
}
140
141
94
void setStatBase(const AttributesT id, const int value, const Notify notify)
142
{
143
94
    const int old = mData.mStats[id].base;
144
94
    mData.mStats[id].base = value;
145
94
    if (notify == Notify_true)
146
94
        triggerStat(id, old, 0);
147
94
}
148
149
int getStatMod(const AttributesT id)
150
{
151
    const StatMap::const_iterator it = mData.mStats.find(id);
152
    if (it != mData.mStats.end())
153
        return it->second.mod;
154
    return 0;
155
}
156
157
94
void setStatMod(const AttributesT id, const int value, const Notify notify)
158
{
159
94
    const int old = mData.mStats[id].mod;
160
94
    mData.mStats[id].mod = value;
161
94
    if (notify == Notify_true)
162
94
        triggerStat(id, old, 0);
163
94
}
164
165
6
int getStatEffective(const AttributesT id)
166
{
167
12
    const StatMap::const_iterator it = mData.mStats.find(id);
168
6
    if (it != mData.mStats.end())
169
        return it->second.base + it->second.mod;
170
    return 0;
171
}
172
173
const std::pair<int, int> getStatExperience(const AttributesT id)
174
{
175
    const StatMap::const_iterator it = mData.mStats.find(id);
176
    int a;
177
    int b;
178
    if (it != mData.mStats.end())
179
    {
180
        a = it->second.exp;
181
        b = it->second.expNeed;
182
    }
183
    else
184
    {
185
        a = 0;
186
        b = 0;
187
    }
188
    return std::pair<int, int>(a, b);
189
}
190
191
// --- Inventory / Equipment --------------------------------------------------
192
193
79
Inventory *getInventory()
194
{
195
79
    return mInventory;
196
}
197
198
Inventory *getStorageInventory()
199
{
200
    if (inventoryHandler != nullptr)
201
        return inventoryHandler->getStorage();
202
    return nullptr;
203
}
204
205
Inventory *getCartInventory()
206
{
207
    return mCartInventory;
208
}
209
210
215
void clearInventory()
211
{
212
215
    if (mEquipment != nullptr)
213
        mEquipment->clear();
214
215
    if (mInventory != nullptr)
215
        mInventory->clear();
216
215
}
217
218
Equipment *getEquipment()
219
{
220
    return mEquipment;
221
}
222
223
const Item *getEquipment(const unsigned int slot)
224
{
225
    if (mEquipment != nullptr)
226
        return mEquipment->getEquipment(slot);
227
    return nullptr;
228
}
229
230
void setEquipmentBackend(Equipment::Backend *const backend)
231
{
232
    if (mEquipment != nullptr)
233
        mEquipment->setBackend(backend);
234
}
235
236
void equipItem(const Item *const item, const Sfx sfx)
237
{
238
    if (sfx == Sfx_true)
239
        ItemSoundManager::playSfx(item, ItemSoundEvent::EQUIP);
240
    if (inventoryHandler != nullptr)
241
        inventoryHandler->equipItem(item);
242
}
243
244
void unequipItem(const Item *const item, const Sfx sfx)
245
{
246
    if (sfx == Sfx_true)
247
        ItemSoundManager::playSfx(item, ItemSoundEvent::UNEQUIP);
248
    if (inventoryHandler != nullptr)
249
        inventoryHandler->unequipItem(item);
250
}
251
252
void useItem(const Item *const item, const Sfx sfx)
253
{
254
    if (sfx == Sfx_true)
255
        ItemSoundManager::playSfx(item, ItemSoundEvent::USE);
256
    if (inventoryHandler != nullptr)
257
        inventoryHandler->useItem(item);
258
}
259
260
void useEquipItem(const Item *const item,
261
                  const int16_t useType,
262
                  const Sfx sfx)
263
{
264
    if (item != nullptr)
265
    {
266
        if (item->getType() == ItemType::Card)
267
        {
268
            if (mProtectedItems.find(item->getId()) == mProtectedItems.end())
269
            {
270
                if (inventoryHandler != nullptr)
271
                    inventoryHandler->useCard(item);
272
                if (sfx == Sfx_true)
273
                    ItemSoundManager::playSfx(item, ItemSoundEvent::USECARD);
274
            }
275
        }
276
        else if (item->isEquipment() == Equipm_true)
277
        {
278
            if (item->isEquipped() == Equipped_true)
279
            {
280
                if (sfx == Sfx_true)
281
                    ItemSoundManager::playSfx(item, ItemSoundEvent::UNEQUIP);
282
                if (inventoryHandler != nullptr)
283
                    inventoryHandler->unequipItem(item);
284
            }
285
            else
286
            {
287
                if (sfx == Sfx_true)
288
                    ItemSoundManager::playSfx(item, ItemSoundEvent::EQUIP);
289
                if (inventoryHandler != nullptr)
290
                    inventoryHandler->equipItem(item);
291
            }
292
        }
293
        else
294
        {
295
            if (mProtectedItems.find(item->getId()) == mProtectedItems.end())
296
            {
297
                if (inventoryHandler != nullptr)
298
                {
299
                    if (useType == 0)
300
                        inventoryHandler->useItem(item);
301
                    else
302
                        inventoryHandler->useItem(item, useType);
303
                }
304
                if (sfx == Sfx_true)
305
                    ItemSoundManager::playSfx(item, ItemSoundEvent::USE);
306
            }
307
        }
308
    }
309
}
310
311
void useEquipItem2(const Item *const item,
312
                   const int16_t useType,
313
                   const Sfx sfx)
314
{
315
    if (item != nullptr)
316
    {
317
        if (item->isEquipment() == Equipm_false)
318
        {
319
            if (item->isEquipped() == Equipped_true)
320
            {
321
                if (sfx == Sfx_true)
322
                    ItemSoundManager::playSfx(item, ItemSoundEvent::UNEQUIP);
323
                if (inventoryHandler != nullptr)
324
                    inventoryHandler->unequipItem(item);
325
            }
326
            else
327
            {
328
                if (sfx == Sfx_true)
329
                    ItemSoundManager::playSfx(item, ItemSoundEvent::EQUIP);
330
                if (inventoryHandler != nullptr)
331
                    inventoryHandler->equipItem(item);
332
            }
333
        }
334
        else
335
        {
336
            if (mProtectedItems.find(item->getId()) == mProtectedItems.end())
337
            {
338
                if (sfx == Sfx_true)
339
                    ItemSoundManager::playSfx(item, ItemSoundEvent::USE);
340
                if (inventoryHandler != nullptr)
341
                {
342
                    if (useType == 0)
343
                        inventoryHandler->useItem(item);
344
                    else
345
                        inventoryHandler->useItem(item, useType);
346
                }
347
            }
348
        }
349
    }
350
}
351
352
void dropItem(const Item *const item, const int amount, const Sfx sfx)
353
{
354
    if (item != nullptr &&
355
        mProtectedItems.find(item->getId()) == mProtectedItems.end())
356
    {
357
        if (sfx == Sfx_true)
358
            ItemSoundManager::playSfx(item, ItemSoundEvent::DROP);
359
        if (inventoryHandler != nullptr)
360
            inventoryHandler->dropItem(item, amount);
361
    }
362
}
363
364
void pickUpItem(const FloorItem *const item, const Sfx sfx)
365
{
366
    if (sfx == Sfx_true)
367
        ItemSoundManager::playSfx(item, ItemSoundEvent::PICKUP);
368
    if (playerHandler != nullptr)
369
        playerHandler->pickUp(item);
370
}
371
372
// --- Misc -------------------------------------------------------------------
373
374
void setBackend(const PlayerInfoBackend &backend)
375
{
376
    mData = backend;
377
}
378
379
void setCharId(const int charId)
380
{
381
    mCharId = charId;
382
}
383
384
int getCharId()
385
{
386
    return mCharId;
387
}
388
389
Trading isTrading()
390
{
391
    return mTrading;
392
}
393
394
void setTrading(const Trading trading)
395
{
396
    mTrading = trading;
397
}
398
399
#define updateAttackStat(atk, delay, speed) \
400
    attackDelay = getStatBase(delay); \
401
    if (attackDelay != 0) \
402
    { \
403
        setStatBase(speed, \
404
            getStatBase(atk) * 1000 / attackDelay, \
405
            Notify_false); \
406
        setStatMod(speed, \
407
            getStatMod(atk) * 1000 / attackDelay, \
408
            Notify_true); \
409
    } \
410
    else \
411
    { \
412
        setStatBase(speed, 0, \
413
            Notify_false); \
414
        setStatMod(speed, 0, \
415
            Notify_true); \
416
    }
417
418
void updateAttrs()
419
{
420
    int attackDelay;
421
    updateAttackStat(Attributes::PLAYER_ATK,
422
        Attributes::PLAYER_ATTACK_DELAY,
423
        Attributes::PLAYER_ATTACK_SPEED)
424
    updateAttackStat(Attributes::HOMUN_ATK,
425
        Attributes::HOMUN_ATTACK_DELAY,
426
        Attributes::HOMUN_ATTACK_SPEED)
427
    updateAttackStat(Attributes::MERC_ATK,
428
        Attributes::MERC_ATTACK_DELAY,
429
        Attributes::MERC_ATTACK_SPEED)
430
}
431
432
void init()
433
{
434
}
435
436
215
void deinit()
437
{
438
215
    clearInventory();
439
215
    delete2(mMercenary);
440
215
    mPetBeingId = BeingId_zero;
441
215
}
442
443
void loadData()
444
{
445
    mProtectedItems.clear();
446
    splitToIntSet(mProtectedItems,
447
        serverConfig.getStringValue("protectedItems"), ',');
448
}
449
450
void clear()
451
{
452
    mData.mSkills.clear();
453
    mPetBeingId = BeingId_zero;
454
}
455
456
bool isTalking()
457
{
458
    return NpcDialog::isActive() || InventoryWindow::isStorageActive();
459
}
460
461
void gameDestroyed()
462
{
463
    delete2(mInventory);
464
    delete2(mEquipment);
465
    delete2(mCartInventory);
466
}
467
468
void stateChange(const StateT state)
469
{
470
    if (state == State::GAME)
471
    {
472
        if (mInventory == nullptr)
473
        {
474
            mInventory = new Inventory(InventoryType::Inventory, -1);
475
            mEquipment = new Equipment;
476
            mCartInventory = new Inventory(InventoryType::Cart, -1);
477
        }
478
    }
479
}
480
481
static void saveProtectedItems()
482
{
483
    std::string str;
484
    std::set<int>::const_iterator it = mProtectedItems.begin();
485
    std::set<int>::const_iterator it_end = mProtectedItems.end();
486
    if (it != it_end)
487
    {
488
        str.append(toString(*it));
489
        ++ it;
490
    }
491
    while (it != it_end)
492
    {
493
        str.append(",").append(toString(*it));
494
        ++ it;
495
    }
496
    serverConfig.setValue("protectedItems", str);
497
    serverConfig.write();
498
}
499
500
void protectItem(const int id)
501
{
502
    mProtectedItems.insert(id);
503
    saveProtectedItems();
504
}
505
506
void unprotectItem(const int id)
507
{
508
    mProtectedItems.erase(id);
509
    saveProtectedItems();
510
}
511
512
bool isItemProtected(const int id)
513
{
514
    return mProtectedItems.find(id) != mProtectedItems.end();
515
}
516
517
void setMercenary(MercenaryInfo *const info)
518
{
519
    delete mMercenary;
520
    mMercenary = info;
521
}
522
523
void setMercenaryBeing(Being *const being)
524
{
525
    if (being == nullptr ||
526
        mMercenary == nullptr)
527
    {
528
        return;
529
    }
530
    being->setName(mMercenary->name);
531
    being->setOwner(localPlayer);
532
    being->setLevel(mMercenary->level);
533
    being->setAttackRange(mMercenary->range);
534
}
535
536
void setElemental(const BeingId id)
537
{
538
    mElementalId = id;
539
}
540
541
BeingId getElementalId()
542
{
543
    return mElementalId;
544
}
545
546
MercenaryInfo *getMercenary()
547
{
548
    return mMercenary;
549
}
550
551
void setPet(PetInfo *const info)
552
{
553
    delete mPet;
554
    mPet = info;
555
}
556
557
void setPetBeing(Being *const being)
558
{
559
    if (being != nullptr)
560
        mPetBeingId = being->getId();
561
    else
562
        mPetBeingId = BeingId_zero;
563
    if (being == nullptr ||
564
        mPet == nullptr)
565
    {
566
        return;
567
    }
568
    being->setName(mPet->name);
569
    being->setOwner(localPlayer);
570
    being->setLevel(mPet->level);
571
}
572
573
PetInfo *getPet()
574
{
575
    return mPet;
576
}
577
578
BeingId getPetBeingId()
579
{
580
    return mPetBeingId;
581
}
582
583
void setHomunculus(HomunculusInfo *const info)
584
{
585
    delete mHomunculus;
586
    mHomunculus = info;
587
}
588
589
void setHomunculusBeing(Being *const being)
590
{
591
    if (being == nullptr ||
592
        mHomunculus == nullptr)
593
    {
594
        return;
595
    }
596
    being->setName(mHomunculus->name);
597
    being->setOwner(localPlayer);
598
}
599
600
HomunculusInfo *getHomunculus()
601
{
602
    return mHomunculus;
603
}
604
605
BeingId getHomunculusId()
606
{
607
    return mHomunculus != nullptr ? mHomunculus->id : BeingId_zero;
608
}
609
610
BeingId getMercenaryId()
611
{
612
    return mMercenary != nullptr ? mMercenary->id : BeingId_zero;
613
}
614
615
void updateAttackAi(const BeingId targetId,
616
                    const Keep keep)
617
{
618
    if (mMercenary != nullptr &&
619
        mercenaryHandler != nullptr)
620
    {
621
        mercenaryHandler->attack(targetId, keep);
622
    }
623
    if (mHomunculus != nullptr &&
624
        homunculusHandler != nullptr)
625
    {
626
        homunculusHandler->attack(targetId, keep);
627
    }
628
}
629
630
std::string getRoomName()
631
{
632
    return mRoomName;
633
}
634
635
void setRoomName(const std::string &name)
636
{
637
    mRoomName = name;
638
}
639
640
bool isInRoom()
641
{
642
    return !mRoomName.empty();
643
}
644
645
void setGuildPositionFlags(const GuildPositionFlags::Type pos)
646
{
647
    mGuildPositionFlags = pos;
648
}
649
650
GuildPositionFlags::Type getGuildPositionFlags()
651
{
652
    return mGuildPositionFlags;
653
}
654
655
void enableVending(const bool b)
656
{
657
    mVending = b;
658
}
659
660
bool isVending()
661
{
662
    return mVending;
663
}
664
665
void setServerLanguage(const int lang)
666
{
667
    if (lang != mServerLanguage)
668
    {
669
        mServerLanguage = lang;
670
        TranslationManager::loadDictionaryLang();
671
    }
672
}
673
674
int getServerLanguage()
675
{
676
    return mServerLanguage;
677
}
678
679

3
}  // namespace PlayerInfo