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

6
}  // namespace PlayerInfo