GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/being/playerinfo.cpp Lines: 37 288 12.8 %
Date: 2017-11-29 Branches: 10 212 4.7 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2010  The Mana Developers
4
 *  Copyright (C) 2011-2017  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
2
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
2
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
2
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
372
    StatListener::distributeEvent(id, old1, old2);
88
}
89
90
// --- Attributes -------------------------------------------------------------
91
92
6
int64_t getAttribute64(const AttributesT id)
93
{
94
12
    const AtrIntMap::const_iterator it = mData.mAttributes.find(id);
95
6
    if (it != mData.mAttributes.end())
96
        return it->second;
97
    return 0;
98
}
99
100
44
int32_t getAttribute(const AttributesT id)
101
{
102
88
    const AtrIntMap::const_iterator it = mData.mAttributes.find(id);
103
44
    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
186
void setStatBase(const AttributesT id, const int value, const Notify notify)
142
{
143
186
    const int old = mData.mStats[id].base;
144
186
    mData.mStats[id].base = value;
145
186
    if (notify == Notify_true)
146
186
        triggerStat(id, old, 0);
147
186
}
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
186
void setStatMod(const AttributesT id, const int value, const Notify notify)
158
{
159
186
    const int old = mData.mStats[id].mod;
160
186
    mData.mStats[id].mod = value;
161
186
    if (notify == Notify_true)
162
186
        triggerStat(id, old, 0);
163
186
}
164
165
12
int getStatEffective(const AttributesT id)
166
{
167
24
    const StatMap::const_iterator it = mData.mStats.find(id);
168
12
    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, b;
177
    if (it != mData.mStats.end())
178
    {
179
        a = it->second.exp;
180
        b = it->second.expNeed;
181
    }
182
    else
183
    {
184
        a = 0;
185
        b = 0;
186
    }
187
    return std::pair<int, int>(a, b);
188
}
189
190
void setStatExperience(const AttributesT id,
191
                       const int have,
192
                       const int need,
193
                       const Notify notify)
194
{
195
    Stat &stat = mData.mStats[id];
196
197
    const int oldExp = stat.exp;
198
    const int oldExpNeed = stat.expNeed;
199
    stat.exp = have;
200
    stat.expNeed = need;
201
    if (notify == Notify_true)
202
        triggerStat(id, oldExp, oldExpNeed);
203
}
204
205
// --- Inventory / Equipment --------------------------------------------------
206
207
156
Inventory *getInventory()
208
{
209
156
    return mInventory;
210
}
211
212
Inventory *getStorageInventory()
213
{
214
    if (inventoryHandler != nullptr)
215
        return inventoryHandler->getStorage();
216
    return nullptr;
217
}
218
219
Inventory *getCartInventory()
220
{
221
    return mCartInventory;
222
}
223
224
362
void clearInventory()
225
{
226
362
    if (mEquipment != nullptr)
227
        mEquipment->clear();
228
362
    if (mInventory != nullptr)
229
        mInventory->clear();
230
362
}
231
232
Equipment *getEquipment()
233
{
234
    return mEquipment;
235
}
236
237
const Item *getEquipment(const unsigned int slot)
238
{
239
    if (mEquipment != nullptr)
240
        return mEquipment->getEquipment(slot);
241
    return nullptr;
242
}
243
244
void setEquipmentBackend(Equipment::Backend *const backend)
245
{
246
    if (mEquipment != nullptr)
247
        mEquipment->setBackend(backend);
248
}
249
250
void equipItem(const Item *const item, const Sfx sfx)
251
{
252
    if (sfx == Sfx_true)
253
        ItemSoundManager::playSfx(item, ItemSoundEvent::EQUIP);
254
    if (inventoryHandler != nullptr)
255
        inventoryHandler->equipItem(item);
256
}
257
258
void unequipItem(const Item *const item, const Sfx sfx)
259
{
260
    if (sfx == Sfx_true)
261
        ItemSoundManager::playSfx(item, ItemSoundEvent::UNEQUIP);
262
    if (inventoryHandler != nullptr)
263
        inventoryHandler->unequipItem(item);
264
}
265
266
void useItem(const Item *const item, const Sfx sfx)
267
{
268
    if (sfx == Sfx_true)
269
        ItemSoundManager::playSfx(item, ItemSoundEvent::USE);
270
    if (inventoryHandler != nullptr)
271
        inventoryHandler->useItem(item);
272
}
273
274
void useEquipItem(const Item *const item,
275
                  const int16_t useType,
276
                  const Sfx sfx)
277
{
278
    if (item != nullptr)
279
    {
280
        if (item->getType() == ItemType::Card)
281
        {
282
            if (mProtectedItems.find(item->getId()) == mProtectedItems.end())
283
            {
284
                if (inventoryHandler != nullptr)
285
                    inventoryHandler->useCard(item);
286
                if (sfx == Sfx_true)
287
                    ItemSoundManager::playSfx(item, ItemSoundEvent::USECARD);
288
            }
289
        }
290
        else if (item->isEquipment() == Equipm_true)
291
        {
292
            if (item->isEquipped() == Equipped_true)
293
            {
294
                if (sfx == Sfx_true)
295
                    ItemSoundManager::playSfx(item, ItemSoundEvent::UNEQUIP);
296
                if (inventoryHandler != nullptr)
297
                    inventoryHandler->unequipItem(item);
298
            }
299
            else
300
            {
301
                if (sfx == Sfx_true)
302
                    ItemSoundManager::playSfx(item, ItemSoundEvent::EQUIP);
303
                if (inventoryHandler != nullptr)
304
                    inventoryHandler->equipItem(item);
305
            }
306
        }
307
        else
308
        {
309
            if (mProtectedItems.find(item->getId()) == mProtectedItems.end())
310
            {
311
                if (inventoryHandler != nullptr)
312
                {
313
                    if (useType == 0)
314
                        inventoryHandler->useItem(item);
315
                    else
316
                        inventoryHandler->useItem(item, useType);
317
                }
318
                if (sfx == Sfx_true)
319
                    ItemSoundManager::playSfx(item, ItemSoundEvent::USE);
320
            }
321
        }
322
    }
323
}
324
325
void useEquipItem2(const Item *const item,
326
                   const int16_t useType,
327
                   const Sfx sfx)
328
{
329
    if (item != nullptr)
330
    {
331
        if (item->isEquipment() == Equipm_false)
332
        {
333
            if (item->isEquipped() == Equipped_true)
334
            {
335
                if (sfx == Sfx_true)
336
                    ItemSoundManager::playSfx(item, ItemSoundEvent::UNEQUIP);
337
                if (inventoryHandler != nullptr)
338
                    inventoryHandler->unequipItem(item);
339
            }
340
            else
341
            {
342
                if (sfx == Sfx_true)
343
                    ItemSoundManager::playSfx(item, ItemSoundEvent::EQUIP);
344
                if (inventoryHandler != nullptr)
345
                    inventoryHandler->equipItem(item);
346
            }
347
        }
348
        else
349
        {
350
            if (mProtectedItems.find(item->getId()) == mProtectedItems.end())
351
            {
352
                if (sfx == Sfx_true)
353
                    ItemSoundManager::playSfx(item, ItemSoundEvent::USE);
354
                if (inventoryHandler != nullptr)
355
                {
356
                    if (useType == 0)
357
                        inventoryHandler->useItem(item);
358
                    else
359
                        inventoryHandler->useItem(item, useType);
360
                }
361
            }
362
        }
363
    }
364
}
365
366
void dropItem(const Item *const item, const int amount, const Sfx sfx)
367
{
368
    if (item != nullptr &&
369
        mProtectedItems.find(item->getId()) == mProtectedItems.end())
370
    {
371
        if (sfx == Sfx_true)
372
            ItemSoundManager::playSfx(item, ItemSoundEvent::DROP);
373
        if (inventoryHandler != nullptr)
374
            inventoryHandler->dropItem(item, amount);
375
    }
376
}
377
378
void pickUpItem(const FloorItem *const item, const Sfx sfx)
379
{
380
    if (sfx == Sfx_true)
381
        ItemSoundManager::playSfx(item, ItemSoundEvent::PICKUP);
382
    if (playerHandler != nullptr)
383
        playerHandler->pickUp(item);
384
}
385
386
// --- Misc -------------------------------------------------------------------
387
388
void setBackend(const PlayerInfoBackend &backend)
389
{
390
    mData = backend;
391
}
392
393
void setCharId(const int charId)
394
{
395
    mCharId = charId;
396
}
397
398
int getCharId()
399
{
400
    return mCharId;
401
}
402
403
Trading isTrading()
404
{
405
    return mTrading;
406
}
407
408
void setTrading(const Trading trading)
409
{
410
    mTrading = trading;
411
}
412
413
#define updateAttackStat(atk, delay, speed) \
414
    attackDelay = getStatBase(delay); \
415
    if (attackDelay != 0) \
416
    { \
417
        setStatBase(speed, \
418
            getStatBase(atk) * 1000 / attackDelay, \
419
            Notify_false); \
420
        setStatMod(speed, \
421
            getStatMod(atk) * 1000 / attackDelay, \
422
            Notify_true); \
423
    } \
424
    else \
425
    { \
426
        setStatBase(speed, 0, \
427
            Notify_false); \
428
        setStatMod(speed, 0, \
429
            Notify_true); \
430
    }
431
432
void updateAttrs()
433
{
434
    int attackDelay;
435
    updateAttackStat(Attributes::PLAYER_ATK,
436
        Attributes::PLAYER_ATTACK_DELAY,
437
        Attributes::PLAYER_ATTACK_SPEED)
438
    updateAttackStat(Attributes::HOMUN_ATK,
439
        Attributes::HOMUN_ATTACK_DELAY,
440
        Attributes::HOMUN_ATTACK_SPEED)
441
    updateAttackStat(Attributes::MERC_ATK,
442
        Attributes::MERC_ATTACK_DELAY,
443
        Attributes::MERC_ATTACK_SPEED)
444
}
445
446
void init()
447
{
448
}
449
450
362
void deinit()
451
{
452
362
    clearInventory();
453
362
    delete2(mMercenary);
454
362
    mPetBeingId = BeingId_zero;
455
362
}
456
457
void loadData()
458
{
459
    mProtectedItems.clear();
460
    splitToIntSet(mProtectedItems,
461
        serverConfig.getStringValue("protectedItems"), ',');
462
}
463
464
void clear()
465
{
466
    mData.mSkills.clear();
467
    mPetBeingId = BeingId_zero;
468
}
469
470
bool isTalking()
471
{
472
    return NpcDialog::isActive() || InventoryWindow::isStorageActive();
473
}
474
475
void gameDestroyed()
476
{
477
    delete2(mInventory);
478
    delete2(mEquipment);
479
    delete2(mCartInventory);
480
}
481
482
void stateChange(const StateT state)
483
{
484
    if (state == State::GAME)
485
    {
486
        if (mInventory == nullptr)
487
        {
488
            mInventory = new Inventory(InventoryType::Inventory);
489
            mEquipment = new Equipment;
490
            mCartInventory = new Inventory(InventoryType::Cart);
491
        }
492
    }
493
}
494
495
static void saveProtectedItems()
496
{
497
    std::string str;
498
    std::set<int>::const_iterator it = mProtectedItems.begin();
499
    std::set<int>::const_iterator it_end = mProtectedItems.end();
500
    if (it != it_end)
501
    {
502
        str.append(toString(*it));
503
        ++ it;
504
    }
505
    while (it != it_end)
506
    {
507
        str.append(",").append(toString(*it));
508
        ++ it;
509
    }
510
    serverConfig.setValue("protectedItems", str);
511
    serverConfig.write();
512
}
513
514
void protectItem(const int id)
515
{
516
    mProtectedItems.insert(id);
517
    saveProtectedItems();
518
}
519
520
void unprotectItem(const int id)
521
{
522
    mProtectedItems.erase(id);
523
    saveProtectedItems();
524
}
525
526
bool isItemProtected(const int id)
527
{
528
    return mProtectedItems.find(id) != mProtectedItems.end();
529
}
530
531
void setMercenary(MercenaryInfo *const info)
532
{
533
    delete mMercenary;
534
    mMercenary = info;
535
}
536
537
void setMercenaryBeing(Being *const being)
538
{
539
    if (being == nullptr ||
540
        mMercenary == nullptr)
541
    {
542
        return;
543
    }
544
    being->setName(mMercenary->name);
545
    being->setOwner(localPlayer);
546
    being->setLevel(mMercenary->level);
547
    being->setAttackRange(mMercenary->range);
548
}
549
550
void setElemental(const BeingId id)
551
{
552
    mElementalId = id;
553
}
554
555
BeingId getElementalId()
556
{
557
    return mElementalId;
558
}
559
560
MercenaryInfo *getMercenary()
561
{
562
    return mMercenary;
563
}
564
565
void setPet(PetInfo *const info)
566
{
567
    delete mPet;
568
    mPet = info;
569
}
570
571
void setPetBeing(Being *const being)
572
{
573
    if (being != nullptr)
574
        mPetBeingId = being->getId();
575
    else
576
        mPetBeingId = BeingId_zero;
577
    if (being == nullptr ||
578
        mPet == nullptr)
579
    {
580
        return;
581
    }
582
    being->setName(mPet->name);
583
    being->setOwner(localPlayer);
584
    being->setLevel(mPet->level);
585
}
586
587
PetInfo *getPet()
588
{
589
    return mPet;
590
}
591
592
BeingId getPetBeingId()
593
{
594
    return mPetBeingId;
595
}
596
597
void setHomunculus(HomunculusInfo *const info)
598
{
599
    delete mHomunculus;
600
    mHomunculus = info;
601
}
602
603
void setHomunculusBeing(Being *const being)
604
{
605
    if (being == nullptr ||
606
        mHomunculus == nullptr)
607
    {
608
        return;
609
    }
610
    being->setName(mHomunculus->name);
611
    being->setOwner(localPlayer);
612
}
613
614
HomunculusInfo *getHomunculus()
615
{
616
    return mHomunculus;
617
}
618
619
BeingId getHomunculusId()
620
{
621
    return mHomunculus != nullptr ? mHomunculus->id : BeingId_zero;
622
}
623
624
BeingId getMercenaryId()
625
{
626
    return mMercenary != nullptr ? mMercenary->id : BeingId_zero;
627
}
628
629
void updateAttackAi(const BeingId targetId,
630
                    const Keep keep)
631
{
632
    if (mMercenary != nullptr &&
633
        mercenaryHandler != nullptr)
634
    {
635
        mercenaryHandler->attack(targetId, keep);
636
    }
637
    if (mHomunculus != nullptr &&
638
        homunculusHandler != nullptr)
639
    {
640
        homunculusHandler->attack(targetId, keep);
641
    }
642
}
643
644
std::string getRoomName()
645
{
646
    return mRoomName;
647
}
648
649
void setRoomName(const std::string &name)
650
{
651
    mRoomName = name;
652
}
653
654
bool isInRoom()
655
{
656
    return !mRoomName.empty();
657
}
658
659
void setGuildPositionFlags(const GuildPositionFlags::Type pos)
660
{
661
    mGuildPositionFlags = pos;
662
}
663
664
GuildPositionFlags::Type getGuildPositionFlags()
665
{
666
    return mGuildPositionFlags;
667
}
668
669
void enableVending(const bool b)
670
{
671
    mVending = b;
672
}
673
674
bool isVending()
675
{
676
    return mVending;
677
}
678
679
void setServerLanguage(const int lang)
680
{
681
    if (lang != mServerLanguage)
682
    {
683
        mServerLanguage = lang;
684
        TranslationManager::loadDictionaryLang();
685
    }
686
}
687
688
int getServerLanguage()
689
{
690
    return mServerLanguage;
691
}
692
693

6
}  // namespace PlayerInfo