GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/effectmanager.cpp Lines: 1 104 1.0 %
Date: 2021-03-17 Branches: 0 148 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2008  Fate <[email protected]>
4
 *  Copyright (C) 2008  Chuck Miller <[email protected]>
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 "effectmanager.h"
25
26
#include "configuration.h"
27
#include "soundmanager.h"
28
29
#include "being/being.h"
30
31
#include "utils/checkutils.h"
32
33
#include "particle/particle.h"
34
35
#include "resources/beingcommon.h"
36
37
#include "debug.h"
38
39
EffectManager *effectManager = nullptr;
40
41
EffectManager::EffectManager() :
42
    mEffects(),
43
    mTimers()
44
{
45
    logger->log1("Effects are now loading");
46
    loadXmlFile(paths.getStringValue("effectsFile"), SkipError_false);
47
    loadXmlFile(paths.getStringValue("effectsPatchFile"), SkipError_true);
48
    loadXmlDir("effectsPatchDir", loadXmlFile)
49
}
50
51
void EffectManager::loadXmlFile(const std::string &fileName,
52
                                const SkipError skipError)
53
{
54
    XML::Document doc(fileName, UseVirtFs_true, skipError);
55
    XmlNodeConstPtrConst root = doc.rootNode();
56
57
    if ((root == nullptr) ||
58
        !xmlNameEqual(root, "being-effects"))
59
    {
60
        logger->log("Error loading being effects file: " + fileName);
61
        return;
62
    }
63
64
    for_each_xml_child_node(node, root)
65
    {
66
        if (xmlNameEqual(node, "include"))
67
        {
68
            const std::string name = XML::getProperty(node, "name", "");
69
            if (!name.empty())
70
                loadXmlFile(name, skipError);
71
            continue;
72
        }
73
        else if (xmlNameEqual(node, "effect"))
74
        {
75
            mEffects.push_back(EffectDescription(
76
                XML::getProperty(node, "id", -1),
77
                XML::getProperty(node, "particle", ""),
78
                XML::getProperty(node, "audio", ""),
79
                XML::getProperty(node, "sprite", "")));
80
        }
81
    }
82
}
83
84
EffectManager::~EffectManager()
85
{
86
}
87
88
bool EffectManager::triggerDirection(const int id,
89
                                     Being *const being,
90
                                     const SpriteDirection::Type &direction)
91
{
92
    int rotation;
93
    switch (direction)
94
    {
95
        case SpriteDirection::DOWN:
96
        case SpriteDirection::DOWNRIGHT:
97
        case SpriteDirection::DOWNLEFT:
98
        case SpriteDirection::DEFAULT:
99
        case SpriteDirection::INVALID:
100
        default:
101
            rotation = 0;
102
            break;
103
        case SpriteDirection::LEFT:
104
            rotation = 90;
105
            break;
106
        case SpriteDirection::UP:
107
        case SpriteDirection::UPRIGHT:
108
        case SpriteDirection::UPLEFT:
109
            rotation = 180;
110
            break;
111
        case SpriteDirection::RIGHT:
112
            rotation = 270;
113
            break;
114
    }
115
116
    return trigger(id, being, rotation);
117
}
118
119
bool EffectManager::trigger(const int id,
120
                            Being *const being,
121
                            const int rotation)
122
{
123
    if ((being == nullptr) || (particleEngine == nullptr) || id == -1)
124
        return false;
125
126
    BLOCK_START("EffectManager::trigger")
127
    bool rValue = false;
128
    FOR_EACH (STD_VECTOR<EffectDescription>::const_iterator, i, mEffects)
129
    {
130
        const EffectDescription &effect = *i;
131
        if (effect.id == id)
132
        {
133
            rValue = true;
134
            if (!effect.gfx.empty())
135
            {
136
                Particle *const selfFX = particleEngine->addEffect(
137
                    effect.gfx, 0, 0, rotation);
138
                being->controlAutoParticle(selfFX);
139
            }
140
            if (!effect.sfx.empty())
141
                soundManager.playSfx(effect.sfx, 0, 0);
142
            if (!effect.sprite.empty())
143
                being->addEffect(effect.sprite);
144
            return rValue;
145
        }
146
    }
147
    reportAlways("Missing effect %d", id)
148
    BLOCK_END("EffectManager::trigger")
149
    return rValue;
150
}
151
152
Particle *EffectManager::triggerReturn(const int id,
153
                                       Being *const being,
154
                                       const int rotation)
155
{
156
    if ((being == nullptr) || (particleEngine == nullptr) || id == -1)
157
        return nullptr;
158
159
    Particle *rValue = nullptr;
160
    FOR_EACH (STD_VECTOR<EffectDescription>::const_iterator, i, mEffects)
161
    {
162
        const EffectDescription &effect = *i;
163
        if (effect.id == id)
164
        {
165
            if (!effect.gfx.empty())
166
            {
167
                rValue = particleEngine->addEffect(
168
                    effect.gfx, 0, 0, rotation);
169
                being->controlCustomParticle(rValue);
170
            }
171
            if (!effect.sfx.empty())
172
                soundManager.playSfx(effect.sfx, 0, 0);
173
            if (!effect.sprite.empty())
174
                being->addEffect(effect.sprite);
175
            return rValue;
176
        }
177
    }
178
    reportAlways("Missing effect %d", id)
179
    return rValue;
180
}
181
182
bool EffectManager::trigger(const int id,
183
                            const int x, const int y,
184
                            const time_t endTime,
185
                            const int rotation)
186
{
187
    if ((particleEngine == nullptr) || id == -1)
188
        return false;
189
190
    bool rValue = false;
191
    FOR_EACH (STD_VECTOR<EffectDescription>::const_iterator, i, mEffects)
192
    {
193
        const EffectDescription &effect = *i;
194
        if (effect.id == id)
195
        {
196
            rValue = true;
197
            if (!effect.gfx.empty())
198
            {
199
                Particle *const particle = particleEngine->addEffect(
200
                    effect.gfx,
201
                    x, y,
202
                    rotation);
203
                if (particle != nullptr)
204
                    mTimers.push_back(ParticleTimer(particle, endTime));
205
            }
206
            if (!effect.sfx.empty())
207
                soundManager.playSfx(effect.sfx, 0, 0);
208
            return rValue;
209
        }
210
    }
211
    reportAlways("Missing effect %d", id)
212
    return rValue;
213
}
214
215
void EffectManager::triggerDefault(int effectId,
216
                                   Being *const being,
217
                                   const int defaultEffectId)
218
{
219
    if (effectId == -1)
220
        effectId = defaultEffectId;
221
    if (effectId == -1)
222
        return;
223
    trigger(effectId, being, 0);
224
}
225
226
void EffectManager::triggerDefault(int effectId,
227
                                   const int x,
228
                                   const int y,
229
                                   const time_t endTime,
230
                                   const int defaultEffectId)
231
{
232
    if (effectId == -1)
233
        effectId = defaultEffectId;
234
    if (effectId == -1)
235
        return;
236
    trigger(effectId, x, y, endTime, 0);
237
}
238
239
void EffectManager::logic()
240
{
241
    const time_t time = cur_time;
242
    bool found(true);
243
    while (found)
244
    {
245
        found = false;
246
        FOR_EACH (std::list<ParticleTimer>::iterator, it, mTimers)
247
        {
248
            const ParticleTimer &timer = *it;
249
            if (timer.endTime < time)
250
            {
251
                found = true;
252
                Particle *const particle = timer.particle;
253
                if (particle != nullptr)
254
                    particle->kill();
255
                mTimers.erase(it);
256
                break;
257
            }
258
        }
259
    }
260
}
261
262
void EffectManager::clear()
263
{
264
    FOR_EACH (std::list<ParticleTimer>::iterator, it, mTimers)
265
    {
266
        Particle *const particle = (*it).particle;
267
        if (particle != nullptr)
268
            particle->kill();
269
    }
270
    mTimers.clear();
271
2
}