GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/resources/beinginfo.cpp Lines: 8 74 10.8 %
Date: 2021-03-17 Branches: 7 68 10.3 %

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-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 "resources/beinginfo.h"
25
26
#include "configuration.h"
27
#include "logger.h"
28
29
#include "const/resources/spriteaction.h"
30
31
#include "enums/resources/map/blockmask.h"
32
33
#include "resources/attack.h"
34
35
#include "resources/sprite/spritereference.h"
36
37
#include "resources/db/colordb.h"
38
39
#include "utils/cast.h"
40
#include "utils/delete2.h"
41
#include "utils/dtor.h"
42
#include "utils/gettext.h"
43
44
#include "debug.h"
45
46
BeingInfo *BeingInfo::unknown = nullptr;
47
1
Attack *BeingInfo::empty = new Attack(SpriteAction::ATTACK,
48
    SpriteAction::ATTACKSKY,
49
    SpriteAction::ATTACKWATER,
50
    SpriteAction::ATTACKRIDE,
51
    -1,
52
    -1,
53
    -1,
54
    -1,
55
2
    std::string(),
56
    32.0F,
57
    7.0F,
58
    8.0F,
59

1
    500);
60
61
BeingInfo::BeingInfo() :
62
    mDisplay(),
63
    // TRANSLATORS: being info default name
64
    mName(_("unnamed")),
65
    mTargetCursorSize(TargetCursorSize::MEDIUM),
66
    mHoverCursor(Cursor::CURSOR_POINTER),
67
    mSounds(),
68
    mAttacks(),
69
    mMenu(),
70
    mStrings(),
71
    mCurrency(),
72
    mBlockWalkMask(BlockMask::WALL |
73
                   BlockMask::AIR |
74
                   BlockMask::WATER |
75
                   BlockMask::MONSTERWALL),
76
    mBlockType(BlockType::NONE),
77
    mColors(nullptr),
78
    mTargetOffsetX(0),
79
    mTargetOffsetY(0),
80
    mNameOffsetX(0),
81
    mNameOffsetY(0),
82
    mHpBarOffsetX(0),
83
    mHpBarOffsetY(0),
84
    mMaxHP(0),
85
    mSortOffsetY(0),
86
    mDeadSortOffsetY(31),
87
    mAvatarId(BeingTypeId_zero),
88
    mWidth(0),
89
    mHeight(0),
90
    mStartFollowDist(3),
91
    mFollowDist(1),
92
    mWarpDist(11),
93
    mWalkSpeed(0),
94
    mSitOffsetX(0),
95
    mSitOffsetY(0),
96
    mMoveOffsetX(0),
97
    mMoveOffsetY(0),
98
    mDeadOffsetX(0),
99
    mDeadOffsetY(0),
100
    mAttackOffsetX(0),
101
    mAttackOffsetY(0),
102
    mThinkTime(50),
103
    mDirectionType(1),
104
    mSitDirectionType(1),
105
    mDeadDirectionType(1),
106
    mAttackDirectionType(1),
107
    mQuickActionEffectId(-1),
108
    mStaticMaxHP(false),
109
    mTargetSelection(true),
110
    mAllowDelete(true),
111
    mAllowEquipment(false)
112
{
113
    SpriteDisplay display;
114
    display.sprites.push_back(SpriteReference::Empty);
115
116
    setDisplay(display);
117
}
118
119
BeingInfo::~BeingInfo()
120
{
121
    delete_all(mSounds);
122
    delete_all(mAttacks);
123
    mSounds.clear();
124
    delete_all(mDisplay.sprites);
125
}
126
127
void BeingInfo::setDisplay(const SpriteDisplay &display)
128
{
129
    mDisplay = display;
130
}
131
132
void BeingInfo::setTargetCursorSize(const std::string &size)
133
{
134
    if (size == "small")
135
    {
136
        setTargetCursorSize(TargetCursorSize::SMALL);
137
    }
138
    else if (size == "medium")
139
    {
140
        setTargetCursorSize(TargetCursorSize::MEDIUM);
141
    }
142
    else if (size == "large")
143
    {
144
        setTargetCursorSize(TargetCursorSize::LARGE);
145
    }
146
    else
147
    {
148
        logger->log("Unknown target cursor type \"%s\" for %s - using medium "
149
                    "sized one", size.c_str(), getName().c_str());
150
        setTargetCursorSize(TargetCursorSize::MEDIUM);
151
    }
152
}
153
154
void BeingInfo::addSound(const ItemSoundEvent::Type event,
155
                         const std::string &filename,
156
                         const int delay)
157
{
158
    if (mSounds.find(event) == mSounds.end())
159
        mSounds[event] = new SoundInfoVect;
160
161
    if (mSounds[event] != nullptr)
162
        mSounds[event]->push_back(SoundInfo(filename, delay));
163
}
164
165
const SoundInfo &BeingInfo::getSound(const ItemSoundEvent::Type event) const
166
{
167
    static SoundInfo emptySound("", 0);
168
169
    const ItemSoundEvents::const_iterator i = mSounds.find(event);
170
171
    if (i == mSounds.end())
172
        return emptySound;
173
174
    const SoundInfoVect *const vect = i->second;
175
    if (vect == nullptr || vect->empty())
176
        return emptySound;
177
    return vect->at(CAST_SIZE(rand()) % vect->size());
178
}
179
180
const Attack *BeingInfo::getAttack(const int id) const
181
{
182
    const Attacks::const_iterator i = mAttacks.find(id);
183
    return (i == mAttacks.end()) ? empty : (*i).second;
184
}
185
186
void BeingInfo::addAttack(const int id,
187
                          const std::string &action,
188
                          const std::string &skyAction,
189
                          const std::string &waterAction,
190
                          const std::string &rideAction,
191
                          const int effectId,
192
                          const int hitEffectId,
193
                          const int criticalHitEffectId,
194
                          const int missEffectId,
195
                          const std::string &missileParticle,
196
                          const float missileZ,
197
                          const float missileSpeed,
198
                          const float missileDieDistance,
199
                          const int missileLifeTime)
200
{
201
    delete mAttacks[id];
202
    mAttacks[id] = new Attack(action,
203
        skyAction,
204
        waterAction,
205
        rideAction,
206
        effectId,
207
        hitEffectId,
208
        criticalHitEffectId,
209
        missEffectId,
210
        missileParticle,
211
        missileZ,
212
        missileSpeed,
213
        missileDieDistance,
214
        missileLifeTime);
215
}
216
217
204
void BeingInfo::clear()
218
{
219
204
    delete2(unknown)
220
204
    delete2(empty)
221
204
}
222
223
void BeingInfo::init()
224
{
225
    if (empty != nullptr)
226
    {
227
        empty->mEffectId = paths.getIntValue("effectId");
228
        empty->mHitEffectId = paths.getIntValue("hitEffectId");
229
        empty->mCriticalHitEffectId = paths.getIntValue("criticalHitEffectId");
230
        empty->mMissEffectId = paths.getIntValue("missEffectId");
231
    }
232
}
233
234
void BeingInfo::setColorsList(const std::string &name)
235
{
236
    if (name.empty())
237
        mColors = nullptr;
238
    else
239
        mColors = ColorDB::getColorsList(name);
240
}
241
242
std::string BeingInfo::getColor(const ItemColor idx) const
243
{
244
    if (mColors == nullptr)
245
        return std::string();
246
247
    const std::map <ItemColor, ItemColorData>::const_iterator
248
        it = mColors->find(idx);
249
    if (it == mColors->end())
250
        return std::string();
251
    return it->second.color;
252
}
253
254
void BeingInfo::addMenu(const std::string &name, const std::string &command)
255
{
256
    mMenu.push_back(BeingMenuItem(name, command));
257
}
258
259
const STD_VECTOR<BeingMenuItem> &BeingInfo::getMenu() const
260
{
261
    return mMenu;
262
}
263
264
std::string BeingInfo::getString(const int idx) const
265
{
266
    const std::map<int, std::string>::const_iterator it = mStrings.find(idx);
267
    if (it == mStrings.end())
268
        return "";
269
    return (*it).second;
270

3
}