1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2012-2015  Joerg Henrichs
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #include "karts/kart_gfx.hpp"
20 
21 #include "config/user_config.hpp"
22 #include "io/file_manager.hpp"
23 #include "graphics/central_settings.hpp"
24 #include "graphics/irr_driver.hpp"
25 #include "graphics/particle_emitter.hpp"
26 #include "graphics/particle_kind.hpp"
27 #include "graphics/particle_kind_manager.hpp"
28 #include "guiengine/engine.hpp"
29 #include "karts/abstract_kart.hpp"
30 #include "karts/controller/controller.hpp"
31 #include "karts/kart.hpp"
32 #include "karts/kart_model.hpp"
33 #include "karts/kart_properties.hpp"
34 #include "karts/skidding.hpp"
35 #include "physics/btKart.hpp"
36 #include "utils/log.hpp"
37 #include "race/race_manager.hpp"
38 
39 #include <iostream>
40 
KartGFX(const AbstractKart * kart,bool is_day)41 KartGFX::KartGFX(const AbstractKart *kart, bool is_day)
42 {
43     m_nitro_light = NULL;
44     m_skidding_light_1 = NULL;
45     m_skidding_light_2 = NULL;
46     m_kart = kart;
47     m_wheel_toggle = 0;
48     m_skid_level = 0;
49 
50     const KartModel *km = m_kart->getKartModel();
51     const float length = km->getLength();
52 
53     scene::ISceneNode *node = m_kart->getNode();
54     // Create nitro light
55     core::vector3df location(0.0f, 0.5f, -0.5f*length - 0.05f);
56 #ifndef SERVER_ONLY
57     if (!GUIEngine::isNoGraphics() && CVS->isGLSL())
58     {
59         m_nitro_light = irr_driver->addLight(location, /*force*/ 0.4f,
60                                              /*radius*/ 5.0f, 0.0f, 0.4f, 1.0f,
61                                              false, node);
62         m_nitro_light->setVisible(false);
63 #ifdef DEBUG
64         m_nitro_light->setName( ("nitro emitter (" + m_kart->getIdent()
65                                                    + ")").c_str() );
66 #endif
67 
68         // Create skidding lights
69         // For the first skidding level
70         m_skidding_light_1 =
71             irr_driver->addLight(core::vector3df(0.0f, 0.1f, -0.5f * length -
72                                  0.05f), /* force */ 0.3f, /*radius*/ 3.0f,
73                                  1.0f, 0.6f, 0.0f, false, node);
74         m_skidding_light_1->setVisible(false);
75         m_skidding_light_1->setName(("skidding emitter 1 (" + m_kart->getIdent()
76                                                             + ")").c_str() );
77 
78         // For the second skidding level
79         m_skidding_light_2 =
80             irr_driver->addLight(core::vector3df(0.0f, 0.1f, -0.5f * length -
81                                  0.05f), /* force */0.4f, /*radius*/4.0f,
82                                  1.0f, 0.1f, 0.0f, false, node);
83         m_skidding_light_2->setVisible(false);
84         m_skidding_light_2->setName(("skidding emitter 2 (" + m_kart->getIdent()
85                                                             + ")").c_str() );
86         m_nitro_light->grab();
87         m_skidding_light_1->grab();
88         m_skidding_light_2->grab();
89     }
90 #endif
91 
92     // Create particle effects
93     Vec3 rear_left(kart->getWheelGraphicsPosition(3).getX(), 0.05f,
94                    kart->getWheelGraphicsPosition(3).getZ()-0.1f    );
95     Vec3 rear_right(kart->getWheelGraphicsPosition(2).getX(), 0.05f,
96                     kart->getWheelGraphicsPosition(2).getZ()-0.1f   );
97 
98     Vec3 rear_center(0, kart->getKartHeight()*0.35f, -0.35f*length);
99 
100     Vec3 rear_nitro_center(0, kart->getKartHeight()*0.2f, -0.1f*length);
101 
102     // FIXME Used to match the emitter as seen in blender
103     const Vec3 delta(0, 0, 0.6f);
104     Vec3 rear_nitro_right = km->getNitroEmittersPositon(0) + delta;
105     Vec3 rear_nitro_left  = km->getNitroEmittersPositon(1) + delta;
106     if (!km->hasNitroEmitters())
107         rear_nitro_right = rear_nitro_left = rear_nitro_center;
108 
109     // Create all effects. Note that they must be created
110     // in the order of KartGFXType.
111     addEffect(KGFX_NITRO1,      "nitro.xml",       rear_nitro_right, true );
112     addEffect(KGFX_NITRO2,      "nitro.xml",       rear_nitro_left,  true );
113     addEffect(KGFX_NITROSMOKE1, "nitro-smoke.xml", rear_nitro_left,  false);
114     addEffect(KGFX_NITROSMOKE2, "nitro-smoke.xml", rear_nitro_right, false);
115     addEffect(KGFX_ZIPPER,      "zipper_fire.xml", rear_center,      true );
116     addEffect(KGFX_TERRAIN,     "smoke.xml",       Vec3(0, 0, 0),    false);
117     addEffect(KGFX_SKID1L,      "skid1.xml",       rear_left,        true );
118     addEffect(KGFX_SKID1R,      "skid1.xml",       rear_right,       true );
119     addEffect(KGFX_SKID2L,      "skid2.xml",       rear_left,        true );
120     addEffect(KGFX_SKID2R,      "skid2.xml",       rear_right,       true );
121     addEffect(KGFX_SKID0L,      "skid0.xml",       rear_left,        true );
122     addEffect(KGFX_SKID0R,      "skid0.xml",       rear_right,       true );
123     if (!kart->getKartModel()->getExhaustXML().empty())
124     {
125         const std::string& ex = kart->getKartModel()->getExhaustXML();
126         addEffect(KGFX_EXHAUST1, ex, rear_nitro_right, false);
127         addEffect(KGFX_EXHAUST2, ex, rear_nitro_left, false);
128     }
129     else
130     {
131         m_all_emitters.push_back(NULL);
132         m_all_emitters.push_back(NULL);
133     }
134 
135 }   // KartGFX
136 
137 // ----------------------------------------------------------------------------
138 /** Destructor. Frees all particle effects and kinds.
139  */
~KartGFX()140 KartGFX::~KartGFX()
141 {
142     for(unsigned int i=0; i<KGFX_COUNT; i++)
143     {
144         if(m_all_emitters[i])
145             delete m_all_emitters[i];
146     }   // for i < KGFX_COUNT
147 
148 #ifndef SERVER_ONLY
149     if (!GUIEngine::isNoGraphics() && CVS->isGLSL())
150     {
151         m_nitro_light->drop();
152         m_skidding_light_1->drop();
153         m_skidding_light_2->drop();
154     }
155 #endif
156 
157 }   // ~KartGFX
158 
159 // ----------------------------------------------------------------------------
160 /** Creates a new particle node with the specified particle kind read from
161  *  the given file.
162  *  \param type The KGFX_ type of this type.
163  *  \param file_name The file name of the particle specification.
164  *  \param position Where on the kart the particles should be emitted.
165  */
addEffect(KartGFXType type,const std::string & file_name,const Vec3 & position,bool important)166 void KartGFX::addEffect(KartGFXType type, const std::string &file_name,
167                         const Vec3 &position, bool important)
168 {
169 #ifndef SERVER_ONLY
170     if (((UserConfigParams::m_particles_effects < 2 || !CVS->isGLSL()) &&
171         (!important || m_kart->getType() == RaceManager::KT_AI ||
172         m_kart->getType() == RaceManager::KT_SPARE_TIRE)) ||
173         UserConfigParams::m_particles_effects < 1 ||
174         GUIEngine::isNoGraphics())
175     {
176         m_all_emitters.push_back(NULL);
177         return;
178     }
179 
180     const ParticleKind *kind    = NULL;
181     ParticleEmitter    *emitter = NULL;
182     try
183     {
184 
185         kind = ParticleKindManager::get()->getParticles(file_name);
186         //kind    = new ParticleKind(file_manager->getGfxFile(file_name));
187         // Skid0 and Skid2 are only used to store the emitter type, and a
188         // wheeless kart has no terrain effects.
189         if(type==KGFX_SKID0L || type==KGFX_SKID0R || type==KGFX_SKID2L || type==KGFX_SKID2R ||
190             (type==KGFX_TERRAIN && m_kart->isWheeless()) )
191             emitter = NULL;
192         else if(type==KGFX_TERRAIN)
193             // Terrain is NOT a child of the kart, since bullet returns the
194             // raycast info in world coordinates
195             emitter = new ParticleEmitter(kind, position, NULL, false,
196                                           important);
197         else
198             emitter = new ParticleEmitter(kind, position, m_kart->getNode(),
199                                           false, important);
200     }
201     catch (std::runtime_error& e)
202     {
203         // If an error happens, mark this emitter as non existant
204         // by adding a NULL to the list (which is tested for in all
205         // cases). C++ guarantees that all memory allocated in the
206         // constructor is properly freed.
207         Log::error("[KartGFX]", "%s",e.what());
208         kind    = NULL;
209         emitter = NULL;
210     }
211     assert((int)m_all_emitters.size()==type);
212     m_all_emitters.push_back(emitter);
213     if (type==KGFX_SKID0L || type==KGFX_SKID0R)
214         m_skid_kind0 = kind;
215     else if(type==KGFX_SKID1L || type==KGFX_SKID1R)
216         m_skid_kind1 = kind;
217     else if (type==KGFX_SKID2L || type==KGFX_SKID2R)
218         m_skid_kind2 = kind;
219 #else
220     m_all_emitters.push_back(NULL);
221 #endif
222 }   // addEffect
223 
224 // ----------------------------------------------------------------------------
225 /** Resets all particle emitters. Used at the (re)start of a race.
226  */
reset()227 void KartGFX::reset()
228 {
229     m_wheel_toggle = 1;
230 #ifndef SERVER_ONLY
231     if (GUIEngine::isNoGraphics())
232         return;
233 
234     for(unsigned int i=0; i<m_all_emitters.size(); i++)
235     {
236         if(m_all_emitters[i])
237         {
238             m_all_emitters[i]->setCreationRateAbsolute(0);
239         }
240     }
241 #endif
242 }   // reset
243 
244 // ----------------------------------------------------------------------------
245 /** Selects the correct skidding particle type depending on skid bonus level.
246  *  \param level Must be 0 (no bonus, showing tiny sparks), 1 (accumulated enough
247  *         for level 1 bonus), or 2 (accumulated enough for level 2 bonus).
248  */
setSkidLevel(const unsigned int level)249 void KartGFX::setSkidLevel(const unsigned int level)
250 {
251     assert(level >= 0);
252     assert(level <= 2);
253     m_skid_level = level;
254     const ParticleKind *pk;
255     if (level == 0)
256     {
257         pk = m_skid_kind0;
258     }
259     else if (level == 1)
260     {
261         pk = m_skid_kind1;
262     }
263     else
264     {
265         pk = m_skid_kind2;
266     }
267 //    const ParticleKind *pk = level==1 ? m_skid_kind1 : m_skid_kind2;
268 #ifndef SERVER_ONLY
269     if (GUIEngine::isNoGraphics())
270         return;
271 
272     if(m_all_emitters[KGFX_SKID1L])
273         m_all_emitters[KGFX_SKID1L]->setParticleType(pk);
274     if(m_all_emitters[KGFX_SKID1R])
275         m_all_emitters[KGFX_SKID1R]->setParticleType(pk);
276     // Relative 0 means it will emitt the minimum rate, i.e. the rate
277     // set to indicate that the bonus is now available.
278     setCreationRateRelative(KartGFX::KGFX_SKIDL, 0.0f);
279     setCreationRateRelative(KartGFX::KGFX_SKIDR, 0.0f);
280 #endif
281 }   // setSkidLevel
282 
283 // ----------------------------------------------------------------------------
284 /** Sets a new particle type to be used. Note that the memory of this
285  *  kind must be managed by the caller.
286  *  \param type The emitter type for which to set the new particle type.
287  *  \param pk The particle kind to use.
288  */
setParticleKind(const KartGFXType type,const ParticleKind * pk)289 void KartGFX::setParticleKind(const KartGFXType type, const ParticleKind *pk)
290 {
291 #ifndef SERVER_ONLY
292     if (GUIEngine::isNoGraphics())
293         return;
294 
295     ParticleEmitter *pe = m_all_emitters[KGFX_TERRAIN];
296     if(!pe) return;
297 
298     pe->setParticleType(pk);
299 #endif
300 }   // setParticleKind
301 
302 // ----------------------------------------------------------------------------
303 /** Defines the new position of the specified emitter.
304  *  \param type The emitter to set a new position for.
305  *  \param xyz The new position of the emitter.
306  */
setXYZ(const KartGFXType type,const Vec3 & xyz)307 void KartGFX::setXYZ(const KartGFXType type, const Vec3 &xyz)
308 {
309 #ifndef SERVER_ONLY
310     if (GUIEngine::isNoGraphics())
311         return;
312 
313     ParticleEmitter *pe = m_all_emitters[KGFX_TERRAIN];
314     if(!pe) return;
315     pe->setPosition(xyz);
316 #endif
317 }   // setXYZ
318 
319 // ----------------------------------------------------------------------------
320 /** Sets the absolute creation rate for the specified particle type.
321  *  \param type The particle effect for which to set the
322  *         creation rate (in particles per seconds).
323  *  \param f The new creation rate.
324  */
setCreationRateAbsolute(KartGFXType type,float f)325 void KartGFX::setCreationRateAbsolute(KartGFXType type, float f)
326 {
327 #ifndef SERVER_ONLY
328     if (GUIEngine::isNoGraphics())
329         return;
330 
331     if (!m_all_emitters[type])
332         return;
333 
334     if (m_all_emitters[type]->getCreationRateFloat() == f)
335         return;
336 
337     m_all_emitters[type]->setCreationRateAbsolute(f);
338 #endif
339 }   // setCreationRateAbsolute
340 
341 // ----------------------------------------------------------------------------
342 /** Sets the creation rate for the specified particle type relative to the
343  *  given minimum and maximum particle rate. If a negative value is
344  *  specified, the creation rate will be set to 0 (absolute).
345  *  \param type The particle effect for which to set the
346  *         creation rate (<0 means no more particles).
347  *  \param f The new relative creation rate.
348  */
setCreationRateRelative(KartGFXType type,float f)349 void KartGFX::setCreationRateRelative(KartGFXType type, float f)
350 {
351 #ifndef SERVER_ONLY
352     if (GUIEngine::isNoGraphics())
353         return;
354 
355     if(m_all_emitters[type])
356     {
357         if(f<0)
358             m_all_emitters[type]->setCreationRateAbsolute(0);
359         else
360             m_all_emitters[type]->setCreationRateRelative(f);
361     }
362 #endif
363 }   // setCreationRateRelative
364 
365 // ----------------------------------------------------------------------------
366 /** Resize the area from which the particles are emitted: the emitter box
367  *  should spread from last frame's position to the current position if
368  *  we want the particles to be emitted in a smooth, continuous flame and not
369  *  in blobs.
370  *  \param type The particle effect for which to resize the emitting box.
371  *  \param new_size New size of the box, typically speed*dt.
372  */
resizeBox(KartGFXType type,float new_size)373 void KartGFX::resizeBox(KartGFXType type, float new_size)
374 {
375 #ifndef SERVER_ONLY
376     if (GUIEngine::isNoGraphics())
377         return;
378 
379     if(m_all_emitters[type])
380         m_all_emitters[type]->resizeBox(std::max(0.25f, new_size));
381 #endif
382 }   // resizeBox
383 
384 // ----------------------------------------------------------------------------
385 /** If necessary defines a new particle type for the terrain emitter. Then
386  *  adjusts the location of the terrain emitter to be in synch with the
387  *  current wheel position, and defines the emission rate depending on speed,
388  *  steering, and skidding.
389  *  \param pk Particle type to use.
390  */
updateTerrain(const ParticleKind * pk)391 void KartGFX::updateTerrain(const ParticleKind *pk)
392 {
393 #ifndef SERVER_ONLY
394     if (GUIEngine::isNoGraphics())
395         return;
396 
397     ParticleEmitter *pe = m_all_emitters[KGFX_TERRAIN];
398     if(!pe) return;
399 
400     pe->setParticleType(pk);
401 
402     const btWheelInfo &wi = m_kart->getVehicle()
403                                   ->getWheelInfo(2+m_wheel_toggle);
404     Vec3 xyz = wi.m_raycastInfo.m_contactPointWS;
405     // FIXME: the X and Z position is not always accurate.
406     xyz.setX(xyz.getX()+ 0.06f * (m_wheel_toggle ? +1 : -1));
407     xyz.setZ(xyz.getZ()+0.06f);
408     pe->setPosition(xyz);
409 
410     // Now compute the particle creation rate:
411     float rate           = 0;
412     const float speed    = fabsf(m_kart->getSpeed());
413     const float skidding = m_kart->getSkidding()->getSkidFactor();
414     // Only create particles when the kart is actually on ground
415     bool on_ground       = m_kart->isOnGround() &&
416                            !m_kart->getSkidding()->isJumping();
417     if (skidding > 1.0f && on_ground)
418         rate = fabsf(m_kart->getControls().getSteer()) > 0.8 ? skidding - 1 : 0;
419     else if (speed >= 0.5f && on_ground)
420         rate = speed/m_kart->getKartProperties()->getEngineMaxSpeed();
421     else
422     {
423         pe->setCreationRateAbsolute(0);
424         return;
425     }
426     // m_skidding can be > 2, and speed > maxSpeed (if powerups are used).
427     if(rate>1.0f) rate = 1.0f;
428     pe->setCreationRateRelative(rate);
429 #endif
430 }   // updateTerrain
431 
432 // ----------------------------------------------------------------------------
433 /** Updates all gfx.
434  *  \param dt Time step size.
435  */
update(float dt)436 void KartGFX::update(float dt)
437 {
438     m_wheel_toggle = 1 - m_wheel_toggle;
439 
440     for (unsigned int i = 0; i < m_all_emitters.size(); i++)
441     {
442         if (m_all_emitters[i])
443             m_all_emitters[i]->update(dt);
444     }
445 
446 }  // update
447 
448 // ----------------------------------------------------------------------------
449 /** Updates nitro dependent particle effects.
450  *  \param nitro_frac Nitro fraction/
451  */
updateNitroGraphics(float nitro_frac)452 void KartGFX::updateNitroGraphics(float nitro_frac)
453 {
454 #ifndef SERVER_ONLY
455     if (GUIEngine::isNoGraphics())
456         return;
457 
458     // Upate particle effects (creation rate, and emitter size
459     // depending on speed)
460     // --------------------------------------------------------
461     if (nitro_frac > 0)
462     {
463         setCreationRateRelative(KartGFX::KGFX_NITRO1, nitro_frac);
464         setCreationRateRelative(KartGFX::KGFX_NITRO2, nitro_frac);
465         setCreationRateRelative(KartGFX::KGFX_NITROSMOKE1, nitro_frac);
466         setCreationRateRelative(KartGFX::KGFX_NITROSMOKE2, nitro_frac);
467 
468         if (CVS->isGLSL())
469             m_nitro_light->setVisible(true);
470     }
471     else
472     {
473         setCreationRateAbsolute(KartGFX::KGFX_NITRO1,      0);
474         setCreationRateAbsolute(KartGFX::KGFX_NITRO2,      0);
475         setCreationRateAbsolute(KartGFX::KGFX_NITROSMOKE1, 0);
476         setCreationRateAbsolute(KartGFX::KGFX_NITROSMOKE2, 0);
477 
478         if (CVS->isGLSL())
479             m_nitro_light->setVisible(false);
480     }
481 
482     // Exhaust is always emitting
483     setCreationRateRelative(KartGFX::KGFX_EXHAUST1, 1.0);
484     setCreationRateRelative(KartGFX::KGFX_EXHAUST2, 1.0);
485 #endif
486 }  // updateGraphics
487 
488 // ----------------------------------------------------------------------------
489 /** Updates the skiddng light (including disabling it).
490  *  \param level Which level of light to display: 0 no light at all,
491  *         1: level 1, 2 level 2.
492  */
updateSkidLight(unsigned int level)493 void KartGFX::updateSkidLight(unsigned int level)
494 {
495 #ifndef SERVER_ONLY
496     if (!GUIEngine::isNoGraphics() && CVS->isGLSL())
497     {
498         m_skidding_light_1->setVisible(level == 1);
499         m_skidding_light_2->setVisible(level > 1);
500     }
501 #endif
502 }   // updateSkidLight
503 
504 // ----------------------------------------------------------------------------
getGFXStatus(int * nitro,bool * zipper,int * skidding,bool * red_skidding) const505 void KartGFX::getGFXStatus(int* nitro, bool* zipper,
506                            int* skidding, bool* red_skidding) const
507 {
508 #ifndef SERVER_ONLY
509     if (GUIEngine::isNoGraphics())
510         return;
511 
512     int n = 0;
513     bool z = false;
514     int s = 0;
515     bool r = false;
516 
517     if (m_all_emitters[KGFX_NITRO1])
518     {
519         n = m_all_emitters[KGFX_NITRO1]->getCreationRate();
520     }
521 
522     if (m_all_emitters[KGFX_ZIPPER])
523     {
524         z = m_all_emitters[KGFX_ZIPPER]->getCreationRate() > 0;
525     }
526 
527     if (m_all_emitters[KGFX_SKIDL])
528     {
529         s = m_all_emitters[KGFX_SKIDL]->getCreationRate();
530         r = m_skid_level == 2;
531     }
532 
533     *nitro = n;
534     *zipper = z;
535     *skidding = s;
536     *red_skidding = r;
537 #endif
538 }   // getGFXStatus
539 
540 // ----------------------------------------------------------------------------
setGFXFromReplay(int nitro,bool zipper,int skidding,bool red_skidding)541 void KartGFX::setGFXFromReplay(int nitro, bool zipper,
542                                int skidding, bool red_skidding)
543 {
544 #ifndef SERVER_ONLY
545     if (GUIEngine::isNoGraphics())
546         return;
547 
548     if (nitro > 0)
549     {
550         setCreationRateAbsolute(KartGFX::KGFX_NITRO1,      (float)nitro);
551         setCreationRateAbsolute(KartGFX::KGFX_NITRO2,      (float)nitro);
552         setCreationRateAbsolute(KartGFX::KGFX_NITROSMOKE1, (float)nitro);
553         setCreationRateAbsolute(KartGFX::KGFX_NITROSMOKE2, (float)nitro);
554 
555         if (CVS->isGLSL())
556             m_nitro_light->setVisible(true);
557     }
558     else
559     {
560         setCreationRateAbsolute(KartGFX::KGFX_NITRO1,      0.0f);
561         setCreationRateAbsolute(KartGFX::KGFX_NITRO2,      0.0f);
562         setCreationRateAbsolute(KartGFX::KGFX_NITROSMOKE1, 0.0f);
563         setCreationRateAbsolute(KartGFX::KGFX_NITROSMOKE2, 0.0f);
564 
565         if (CVS->isGLSL())
566             m_nitro_light->setVisible(false);
567     }
568 
569     if (zipper)
570         setCreationRateAbsolute(KartGFX::KGFX_ZIPPER, 800.0f);
571 
572     if (skidding > 0)
573     {
574         const ParticleKind* skid_kind = red_skidding ? m_skid_kind2
575                                                      : m_skid_kind1;
576 
577         if (m_all_emitters[KGFX_SKID1L])
578             m_all_emitters[KGFX_SKID1L]->setParticleType(skid_kind);
579         if (m_all_emitters[KGFX_SKID1R])
580             m_all_emitters[KGFX_SKID1R]->setParticleType(skid_kind);
581 
582         if (CVS->isGLSL())
583         {
584             m_skidding_light_1->setVisible(!red_skidding);
585             m_skidding_light_2->setVisible(red_skidding);
586         }
587 
588         setCreationRateAbsolute(KartGFX::KGFX_SKIDL, (float)skidding);
589         setCreationRateAbsolute(KartGFX::KGFX_SKIDR, (float)skidding);
590     }
591     else
592     {
593         setCreationRateAbsolute(KartGFX::KGFX_SKIDL, 0.0f);
594         setCreationRateAbsolute(KartGFX::KGFX_SKIDR, 0.0f);
595 
596         if (CVS->isGLSL())
597         {
598             m_skidding_light_1->setVisible(false);
599             m_skidding_light_2->setVisible(false);
600         }
601     }
602 #endif
603 }   // setGFXFromReplay
604 
605 // ----------------------------------------------------------------------------
setGFXInvisible()606 void KartGFX::setGFXInvisible()
607 {
608 #ifndef SERVER_ONLY
609     if (!GUIEngine::isNoGraphics() && CVS->isGLSL())
610     {
611         m_nitro_light->setVisible(false);
612         m_skidding_light_1->setVisible(false);
613         m_skidding_light_2->setVisible(false);
614         m_kart->getKartModel()->toggleHeadlights(false);
615     }
616 #endif
617 }   // setGFXInvisible
618