ManaPlus
effectmanager.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2008 Fate <[email protected]>
4  * Copyright (C) 2008 Chuck Miller <[email protected]>
5  * Copyright (C) 2011-2018 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 
39 
41  mEffects(),
42  mTimers()
43 {
44  logger->log1("Effects are now loading");
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 
84 {
85 }
86 
88  Being *const being,
89  const SpriteDirection::Type &direction)
90 {
91  int rotation;
92  switch (direction)
93  {
99  default:
100  rotation = 0;
101  break;
103  rotation = 90;
104  break;
105  case SpriteDirection::UP:
108  rotation = 180;
109  break;
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, 0, 0);
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 
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, 0, 0);
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, 0, 0);
207  return rValue;
208  }
209  }
210  reportAlways("Missing effect %d", id);
211  return rValue;
212 }
213 
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, 0);
223 }
224 
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, 0);
236 }
237 
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 
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 }
#define FOR_EACH(type, iter, array)
Definition: foreach.h:24
std::string getStringValue(const std::string &key) const
const bool SkipError_false
Definition: skiperror.h:29
void log1(const char *const log_text)
Definition: logger.cpp:222
Particle * addEffect(const std::string &particleEffectFile, const int pixelX, const int pixelY, const int rotation)
std::string fileName
Definition: testmain.cpp:36
std::vector< EffectDescription > mEffects
Definition: effectmanager.h:95
#define BLOCK_START(name)
Definition: perfomance.h:78
SoundManager soundManager
ParticleEngine * particleEngine
int getProperty(const xmlNodePtr node, const char *const name, int def)
Definition: libxml.cpp:171
#define BLOCK_END(name)
Definition: perfomance.h:79
bool triggerDirection(const int id, Being *const being, const SpriteDirection::Type &direction)
void controlAutoParticle(Particle *const particle)
void kill()
Definition: particle.h:219
#define loadXmlDir(name, function)
Definition: beingcommon.h:38
Logger * logger
Definition: logger.cpp:95
void controlCustomParticle(Particle *const particle)
void triggerDefault(int effectId, Being *const being, const int defaultEffectId)
const bool UseVirtFs_true
Definition: usevirtfs.h:29
Particle * triggerReturn(const int id, Being *const being, const int rotation)
volatile time_t cur_time
Definition: timer.cpp:57
xmlNodePtr rootNode()
Definition: libxml.cpp:166
Particle *const particle
Definition: particletimer.h:39
Configuration paths
std::list< ParticleTimer > mTimers
Definition: effectmanager.h:96
#define for_each_xml_child_node(var, parent)
Definition: libxml.h:160
const time_t endTime
Definition: particletimer.h:40
void log(const char *const log_text,...)
Definition: logger.cpp:243
const bool SkipError_true
Definition: skiperror.h:29
void loadXmlFile(const std::string &fileName, const SkipError skipError)
bool trigger(const int id, Being *const being, const int rotation)
Definition: being.h:93
void addEffect(const std::string &name)
Definition: being.cpp:4930
EffectManager * effectManager
#define reportAlways(...)
Definition: checkutils.h:252
void playSfx(const std::string &path, const int x, const int y) const