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