GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/effectmanager.cpp Lines: 1 102 1.0 %
Date: 2017-11-29 Branches: 0 146 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-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "effectmanager.h"
24
25
#include "configuration.h"
26
#include "soundmanager.h"
27
28
#include "being/being.h"
29
30
#include "utils/checkutils.h"
31
32
#include "particle/particle.h"
33
34
#include "resources/beingcommon.h"
35
36
#include "debug.h"
37
38
EffectManager *effectManager = nullptr;
39
40
EffectManager::EffectManager() :
41
    mEffects(),
42
    mTimers()
43
{
44
    logger->log1("Effects are now loading");
45
    loadXmlFile(paths.getStringValue("effectsFile"), SkipError_false);
46
    loadXmlFile(paths.getStringValue("effectsPatchFile"), SkipError_true);
47
    loadXmlDir("effectsPatchDir", loadXmlFile);
48
}
49
50
void EffectManager::loadXmlFile(const std::string &fileName,
51
                                const SkipError skipError)
52
{
53
    XML::Document doc(fileName, UseVirtFs_true, skipError);
54
    XmlNodeConstPtrConst root = doc.rootNode();
55
56
    if ((root == nullptr) ||
57
        !xmlNameEqual(root, "being-effects"))
58
    {
59
        logger->log("Error loading being effects file: " + fileName);
60
        return;
61
    }
62
63
    for_each_xml_child_node(node, root)
64
    {
65
        if (xmlNameEqual(node, "include"))
66
        {
67
            const std::string name = XML::getProperty(node, "name", "");
68
            if (!name.empty())
69
                loadXmlFile(name, skipError);
70
            continue;
71
        }
72
        else if (xmlNameEqual(node, "effect"))
73
        {
74
            mEffects.push_back(EffectDescription(
75
                XML::getProperty(node, "id", -1),
76
                XML::getProperty(node, "particle", ""),
77
                XML::getProperty(node, "audio", ""),
78
                XML::getProperty(node, "sprite", "")));
79
        }
80
    }
81
}
82
83
EffectManager::~EffectManager()
84
{
85
}
86
87
bool EffectManager::triggerDirection(const int id,
88
                                     Being *const being,
89
                                     const SpriteDirection::Type &direction)
90
{
91
    int rotation;
92
    switch (direction)
93
    {
94
        case SpriteDirection::DOWN:
95
        case SpriteDirection::DOWNRIGHT:
96
        case SpriteDirection::DOWNLEFT:
97
        case SpriteDirection::DEFAULT:
98
        case SpriteDirection::INVALID:
99
        default:
100
            rotation = 0;
101
            break;
102
        case SpriteDirection::LEFT:
103
            rotation = 90;
104
            break;
105
        case SpriteDirection::UP:
106
        case SpriteDirection::UPRIGHT:
107
        case SpriteDirection::UPLEFT:
108
            rotation = 180;
109
            break;
110
        case SpriteDirection::RIGHT:
111
            rotation = 270;
112
            break;
113
    }
114
115
    return trigger(id, being, rotation);
116
}
117
118
bool EffectManager::trigger(const int id,
119
                            Being *const being,
120
                            const int rotation)
121
{
122
    if ((being == nullptr) || (particleEngine == nullptr) || id == -1)
123
        return false;
124
125
    BLOCK_START("EffectManager::trigger")
126
    bool rValue = false;
127
    FOR_EACH (STD_VECTOR<EffectDescription>::const_iterator, i, mEffects)
128
    {
129
        const EffectDescription &effect = *i;
130
        if (effect.id == id)
131
        {
132
            rValue = true;
133
            if (!effect.gfx.empty())
134
            {
135
                Particle *const selfFX = particleEngine->addEffect(
136
                    effect.gfx, 0, 0, rotation);
137
                being->controlAutoParticle(selfFX);
138
            }
139
            if (!effect.sfx.empty())
140
                soundManager.playSfx(effect.sfx);
141
            if (!effect.sprite.empty())
142
                being->addEffect(effect.sprite);
143
            return rValue;
144
        }
145
    }
146
    reportAlways("Missing effect %d", id);
147
    BLOCK_END("EffectManager::trigger")
148
    return rValue;
149
}
150
151
Particle *EffectManager::triggerReturn(const int id,
152
                                       Being *const being,
153
                                       const int rotation)
154
{
155
    if ((being == nullptr) || (particleEngine == nullptr) || id == -1)
156
        return nullptr;
157
158
    Particle *rValue = nullptr;
159
    FOR_EACH (STD_VECTOR<EffectDescription>::const_iterator, i, mEffects)
160
    {
161
        const EffectDescription &effect = *i;
162
        if (effect.id == id)
163
        {
164
            if (!effect.gfx.empty())
165
            {
166
                rValue = particleEngine->addEffect(
167
                    effect.gfx, 0, 0, rotation);
168
                being->controlCustomParticle(rValue);
169
            }
170
            if (!effect.sfx.empty())
171
                soundManager.playSfx(effect.sfx);
172
            if (!effect.sprite.empty())
173
                being->addEffect(effect.sprite);
174
            return rValue;
175
        }
176
    }
177
    reportAlways("Missing effect %d", id);
178
    return rValue;
179
}
180
181
bool EffectManager::trigger(const int id,
182
                            const int x, const int y,
183
                            const time_t endTime,
184
                            const int rotation)
185
{
186
    if ((particleEngine == nullptr) || id == -1)
187
        return false;
188
189
    bool rValue = false;
190
    FOR_EACH (STD_VECTOR<EffectDescription>::const_iterator, i, mEffects)
191
    {
192
        const EffectDescription &effect = *i;
193
        if (effect.id == id)
194
        {
195
            rValue = true;
196
            if (!effect.gfx.empty())
197
            {
198
                Particle *const particle = particleEngine->addEffect(
199
                    effect.gfx,
200
                    x, y,
201
                    rotation);
202
                if (particle != nullptr)
203
                    mTimers.push_back(ParticleTimer(particle, endTime));
204
            }
205
            if (!effect.sfx.empty())
206
                soundManager.playSfx(effect.sfx);
207
            return rValue;
208
        }
209
    }
210
    reportAlways("Missing effect %d", id);
211
    return rValue;
212
}
213
214
void EffectManager::triggerDefault(int effectId,
215
                                   Being *const being,
216
                                   const int defaultEffectId)
217
{
218
    if (effectId == -1)
219
        effectId = defaultEffectId;
220
    if (effectId == -1)
221
        return;
222
    trigger(effectId, being);
223
}
224
225
void EffectManager::triggerDefault(int effectId,
226
                                   const int x,
227
                                   const int y,
228
                                   const time_t endTime,
229
                                   const int defaultEffectId)
230
{
231
    if (effectId == -1)
232
        effectId = defaultEffectId;
233
    if (effectId == -1)
234
        return;
235
    trigger(effectId, x, y, endTime);
236
}
237
238
void EffectManager::logic()
239
{
240
    const time_t time = cur_time;
241
    bool found(true);
242
    while (found)
243
    {
244
        found = false;
245
        FOR_EACH (std::list<ParticleTimer>::iterator, it, mTimers)
246
        {
247
            const ParticleTimer &timer = *it;
248
            if (timer.endTime < time)
249
            {
250
                found = true;
251
                Particle *const particle = timer.particle;
252
                if (particle != nullptr)
253
                    particle->kill();
254
                mTimers.erase(it);
255
                break;
256
            }
257
        }
258
    }
259
}
260
261
void EffectManager::clear()
262
{
263
    FOR_EACH (std::list<ParticleTimer>::iterator, it, mTimers)
264
    {
265
        Particle *const particle = (*it).particle;
266
        if (particle != nullptr)
267
            particle->kill();
268
    }
269
    mTimers.clear();
270
4
}