1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2010-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/max_speed.hpp"
20 
21 #include "config/stk_config.hpp"
22 #include "karts/abstract_kart.hpp"
23 #include "karts/kart_properties.hpp"
24 #include "network/network_string.hpp"
25 #include "physics/btKart.hpp"
26 
27 #include <algorithm>
28 #include <assert.h>
29 #include <cstdlib>
30 
31 /** This class handles maximum speed for karts. Several factors can influence
32  *  the maximum speed a kart can drive, some will decrease the maximum speed,
33  *  some will increase the maximum speed.
34  *  Slowdowns are specified in fraction of the (kart specific) maximum speed
35  *  of that kart. The following categories are defined:
36  *  - terrain-specific slow downs
37  *  - AI related slow down (low level AIs might drive slower than player)
38  *  - end controller related AI (end controller drives slower)
39  *  The largest slowdown of all those factors is applied to the maximum
40  *  speed of the kart.
41  *  Increase of maximum speed is given absolute, i.e. in m/s. The following
42  *  circumstances can increase the maximum speed:
43  *  - Use of a zipper
44  *  - Use of sliptstream
45  *  - Use of nitro
46  *  The speed increases for all those are added after applying the maximum
47  *  slowdown fraction.
48  *  At the end the maximum is capped by a value specified in stk_config
49  *  (to avoid issues with physics etc).
50 */
MaxSpeed(AbstractKart * kart)51 MaxSpeed::MaxSpeed(AbstractKart *kart)
52 {
53     m_kart = kart;
54     // Initialise m_add_engine_force since it might be queried before
55     // update() is called.
56     m_add_engine_force  = 0;
57     // This can be used if command line option -N is used
58     m_current_max_speed = 0;
59 }   // MaxSpeed
60 
61 // ----------------------------------------------------------------------------
62 /** Reset to prepare for a restart. It just overwrites each entry with a
63  *  newly constructed values, i.e. values that don't cause any slowdown
64  *  or speedup.
65  */
reset()66 void MaxSpeed::reset()
67 {
68     m_current_max_speed = m_kart->getKartProperties()->getEngineMaxSpeed();
69     m_min_speed         = -1.0f;
70 
71     for(unsigned int i=MS_DECREASE_MIN; i<MS_DECREASE_MAX; i++)
72     {
73         SpeedDecrease sd;
74         m_speed_decrease[i] = sd;
75     }
76 
77     // Then add the speed increase from each category
78     // ----------------------------------------------
79     for(unsigned int i=MS_INCREASE_MIN; i<MS_INCREASE_MAX; i++)
80     {
81         SpeedIncrease si;
82         m_speed_increase[i] = si;
83     }
84 }   // reset
85 
86 // ----------------------------------------------------------------------------
87 /** Sets an increased maximum speed for a category.
88  *  \param category The category for which to set the higher maximum speed.
89  *  \param add_speed How much speed (in m/s) is added to the maximum speed.
90  *  \param duration How long the speed increase will last.
91  *  \param fade_out_time How long the maximum speed will fade out linearly.
92  */
increaseMaxSpeed(unsigned int category,float add_speed,float engine_force,int duration,int fade_out_time)93 void MaxSpeed::increaseMaxSpeed(unsigned int category, float add_speed,
94                                 float engine_force, int duration,
95                                 int fade_out_time)
96 {
97     // Allow fade_out_time 0 if add_speed is set to 0.
98     assert(add_speed==0.0f || fade_out_time>0.01f);
99     assert(category>=MS_INCREASE_MIN && category <MS_INCREASE_MAX);
100 
101     if (add_speed < 0.0f || engine_force < 0.0f)
102     {
103         Log::warn("MaxSpeed::increaseMaxSpeed",
104             "Negative add_speed %f or engine_force %f, ignored.",
105             add_speed, engine_force);
106         return;
107     }
108 
109     int add_speed_i = (int)(add_speed * 1000.0f);
110     if (add_speed_i > 65535)
111     {
112         Log::warn("MaxSpeed::increaseMaxSpeed",
113             "%f add_speed too large.", add_speed);
114         add_speed_i = 65535;
115     }
116 
117     int engine_force_i = (int)(engine_force * 10.0f);
118     if (engine_force_i > 65535)
119     {
120         Log::warn("MaxSpeed::increaseMaxSpeed",
121             "%f engine_force too large.", engine_force);
122         engine_force_i = 65535;
123     }
124 
125     int16_t fade = 0;
126     if (fade_out_time > 32767)
127     {
128         Log::warn("MaxSpeed::increaseMaxSpeed",
129             "%d fade_out_time too large.", fade);
130         fade = (int16_t)32767;
131     }
132     else
133         fade = (int16_t)fade_out_time;
134 
135     int16_t dur = 0;
136     if (duration > 32767)
137     {
138         Log::warn("MaxSpeed::increaseMaxSpeed",
139             "%d duration too large.", dur);
140         dur = (int16_t)32767;
141     }
142     else
143         dur = (int16_t)duration;
144 
145     m_speed_increase[category].m_max_add_speed = (uint16_t)add_speed_i;
146     m_speed_increase[category].m_duration        = dur;
147     m_speed_increase[category].m_fade_out_time   = fade;
148     m_speed_increase[category].m_current_speedup = add_speed;
149     m_speed_increase[category].m_engine_force = (uint16_t)engine_force_i;
150 }   // increaseMaxSpeed
151 
152 // ----------------------------------------------------------------------------
153 /** This adjusts the top speed using increaseMaxSpeed, but additionally
154  *  causes an instant speed boost, which can be smaller than add-max-speed.
155  *  (e.g. a zipper can give an instant boost of 5 m/s, but over time would
156  *  allow the speed to go up by 10 m/s). Note that bullet does not restrict
157  *  speed (e.g. by simulating air resistance), so without capping the speed
158  *  (which is done my this object) the speed would go arbitrary high over time
159  *  \param category The category for which the speed is increased.
160  *  \param add_max_speed Increase of the maximum allowed speed.
161  *  \param speed_boost An instant speed increase for this kart.
162  *  \param engine_force Additional engine force.
163  *  \param duration Duration of the increased speed.
164  *  \param fade_out_time How long the maximum speed will fade out linearly.
165  */
instantSpeedIncrease(unsigned int category,float add_max_speed,float speed_boost,float engine_force,int duration,int fade_out_time)166 void MaxSpeed::instantSpeedIncrease(unsigned int category,
167                                    float add_max_speed, float speed_boost,
168                                    float engine_force, int duration,
169                                    int fade_out_time)
170 {
171     increaseMaxSpeed(category, add_max_speed, engine_force, duration,
172                      fade_out_time);
173     // This will result in all max speed settings updated, but no
174     // changes to any slow downs since dt=0
175     update(0);
176     float speed = std::min(m_kart->getSpeed()+ speed_boost,
177                            getCurrentMaxSpeed() );
178 
179     // If there is a min_speed defined, make sure that the kart is still
180     // fast enough (otherwise e.g. on easy difficulty even with zipper
181     // the speed might be too low for certain jumps).
182     if(speed < m_min_speed) speed = m_min_speed;
183 
184     m_kart->getVehicle()->setMinSpeed(speed);
185 
186 }   // instantSpeedIncrease
187 
188 // ----------------------------------------------------------------------------
189 /** Handles the update of speed increase objects. The m_duration variable
190  *  contains the remaining time - as long as this variable is positive
191  *  the maximum speed increase applies, while when it is between
192  *  -m_fade_out_time and 0, the maximum speed will linearly decrease.
193  *  \param dt Time step size.
194  */
update(int ticks)195 void MaxSpeed::SpeedIncrease::update(int ticks)
196 {
197     if (m_duration == std::numeric_limits<int16_t>::min())
198     {
199         m_current_speedup = 0;
200         m_max_add_speed = 0;
201         return;
202     }
203     m_duration -= ticks;
204     // End of increased max speed reached.
205     if(m_duration < -m_fade_out_time)
206     {
207         m_duration = std::numeric_limits<int16_t>::min();
208         m_current_speedup = 0;
209         m_max_add_speed = 0;
210         return;
211     }
212     // If we are still in main max speed increase time, do nothing
213     m_current_speedup = (float)m_max_add_speed / 1000.0f;
214     if (m_duration > 0)
215         return;
216 
217     // Now we are in the fade out period: decrease time linearly
218     m_current_speedup -= std::abs(m_duration - ticks) *
219         ((float)m_max_add_speed / 1000.0f) / m_fade_out_time;
220 }   // SpeedIncrease::update
221 
222 // ----------------------------------------------------------------------------
saveState(BareNetworkString * buffer) const223 void MaxSpeed::SpeedIncrease::saveState(BareNetworkString *buffer) const
224 {
225     buffer->addUInt16(m_max_add_speed);
226     buffer->addUInt16(m_duration);
227     buffer->addUInt16(m_fade_out_time);
228     buffer->addUInt16(m_engine_force);
229 }   // saveState
230 
231 // ----------------------------------------------------------------------------
rewindTo(BareNetworkString * buffer,bool is_active)232 void MaxSpeed::SpeedIncrease::rewindTo(BareNetworkString *buffer,
233                                        bool is_active)
234 {
235     if(is_active)
236     {
237         m_max_add_speed   = buffer->getUInt16();
238         m_duration        = buffer->getUInt16();
239         m_fade_out_time   = buffer->getUInt16();
240         m_engine_force    = buffer->getUInt16();
241     }
242     else   // make sure to disable this category
243     {
244         reset();
245     }
246 }   // rewindTo
247 
248 // ----------------------------------------------------------------------------
249 /** Defines a slowdown, which is in fraction of top speed.
250  *  \param category The category for which the speed is increased.
251  *  \param max_speed_fraction Fraction of top speed to allow only.
252  *  \param fade_in_time How long till maximum speed is capped.
253  *  \param duration How long the effect will lasts. The value of -1 (default)
254  *         indicates that this effect stays active forever (i.e. till its
255  *         value is changed to something else).
256  */
setSlowdown(unsigned int category,float max_speed_fraction,int fade_in_ticks,int duration)257 void MaxSpeed::setSlowdown(unsigned int category, float max_speed_fraction,
258                            int fade_in_ticks, int duration)
259 {
260     assert(category>=MS_DECREASE_MIN && category <MS_DECREASE_MAX);
261     if (max_speed_fraction < 0.0f)
262     {
263         Log::warn("MaxSpeed::increaseMaxSpeed",
264             "Negative max_speed_fraction %f, ignored.",
265             max_speed_fraction);
266         return;
267     }
268 
269     int max_speed_fraction_i = (int)(max_speed_fraction * 1000.0f);
270     if (max_speed_fraction_i > 65535)
271     {
272         Log::warn("MaxSpeed::increaseMaxSpeed",
273             "%f max_speed_fraction too large.", max_speed_fraction);
274         max_speed_fraction_i = 65535;
275     }
276 
277     int16_t fade = 0;
278     if (fade_in_ticks > 32767)
279     {
280         Log::warn("MaxSpeed::setSlowdown",
281             "%d fade_in_ticks too large.", fade);
282         fade = (int16_t)32767;
283     }
284     else
285         fade = (int16_t)fade_in_ticks;
286 
287     int16_t dur = 0;
288     if (duration > 32767)
289     {
290         Log::warn("MaxSpeed::setSlowdown",
291             "%d duration too large.", dur);
292         dur = (int16_t)32767;
293     }
294     else
295         dur = (int16_t)duration;
296 
297     m_speed_decrease[category].m_fade_in_ticks = fade;
298     m_speed_decrease[category].m_duration = dur;
299     m_speed_decrease[category].m_max_speed_fraction =
300         (uint16_t)max_speed_fraction_i;
301 }   // setSlowdown
302 
303 // ----------------------------------------------------------------------------
304 /** Handles the speed increase for a certain category.
305  *  \param dt Time step size.
306  */
update(int ticks)307 void MaxSpeed::SpeedDecrease::update(int ticks)
308 {
309     if(m_duration>-1)
310     {
311         // It's a timed slowdown
312         m_duration -= ticks;
313         if(m_duration<0)
314         {
315             m_duration           = 0;
316             m_current_fraction   = 1.0f;
317             m_max_speed_fraction = 1000;
318             return;
319         }
320     }
321 
322     float diff = m_current_fraction - m_max_speed_fraction / 1000.0f;
323 
324     if (diff > 0)
325     {
326         if (diff * m_fade_in_ticks > ticks)
327             m_current_fraction -= float(ticks) / float(m_fade_in_ticks);
328         else
329             m_current_fraction = m_max_speed_fraction / 1000.0f;
330     }
331     else
332         m_current_fraction = m_max_speed_fraction / 1000.0f;
333 }   // SpeedDecrease::update
334 
335 // ----------------------------------------------------------------------------
336 /** Saves the state of an (active) speed decrease category. It is not called
337  *  if the speed decrease is not active.
338  *  \param buffer Buffer which will store the state information.
339  */
saveState(BareNetworkString * buffer) const340 void MaxSpeed::SpeedDecrease::saveState(BareNetworkString *buffer) const
341 {
342     buffer->addUInt16(m_max_speed_fraction);
343     buffer->addFloat(m_current_fraction);
344     buffer->addUInt16(m_fade_in_ticks);
345     buffer->addUInt16(m_duration);
346 }   // saveState
347 
348 // ----------------------------------------------------------------------------
349 /** Restores a previously saved state for an active speed decrease category.
350  */
rewindTo(BareNetworkString * buffer,bool is_active)351 void MaxSpeed::SpeedDecrease::rewindTo(BareNetworkString *buffer,
352                                        bool is_active)
353 {
354     if(is_active)
355     {
356         m_max_speed_fraction = buffer->getUInt16();
357         m_current_fraction   = buffer->getFloat();
358         m_fade_in_ticks      = buffer->getUInt16();
359         m_duration           = buffer->getUInt16();
360     }
361     else   // make sure it is not active
362     {
363         reset();
364     }
365 }   // rewindTo
366 
367 // ----------------------------------------------------------------------------
368 /** Returns how much increased speed time is left over in the given category.
369  *  \param category Which category to report on.
370  */
getSpeedIncreaseTicksLeft(unsigned int category)371 int MaxSpeed::getSpeedIncreaseTicksLeft(unsigned int category)
372 {
373     return m_speed_increase[category].getTimeLeft();
374 }   // getSpeedIncreaseTimeLeft
375 
376 // ----------------------------------------------------------------------------
377 /** Returns if increased speed is active in the given category.
378  *  \param category Which category to report on.
379  */
isSpeedIncreaseActive(unsigned int category)380 int MaxSpeed::isSpeedIncreaseActive(unsigned int category)
381 {
382     return m_speed_increase[category].isActive();
383 }   // isSpeedIncreaseActive
384 
385 // ----------------------------------------------------------------------------
386 /** Returns if decreased speed is active in the given category.
387  *  \param category Which category to report on.
388  */
isSpeedDecreaseActive(unsigned int category)389 int MaxSpeed::isSpeedDecreaseActive(unsigned int category)
390 {
391     return m_speed_decrease[category].isActive();
392 }   // isSpeedDecreaseActive
393 
394 // ----------------------------------------------------------------------------
395 /** Updates all speed increase and decrease objects, and determines the
396  *  current maximum speed. Note that the function can be called with
397  *  dt=0, in which case the maximum speed will be updated, but no
398  *  change to any of the speed increase/decrease objects will be done.
399  *  \param dt Time step size (dt=0 only updates the current maximum speed).
400  */
update(int ticks)401 void MaxSpeed::update(int ticks)
402 {
403 
404     // First compute the minimum max-speed fraction, which
405     // determines the overall decrease of maximum speed.
406     // ---------------------------------------------------
407     float slowdown_factor = 1.0f;
408     for(unsigned int i=MS_DECREASE_MIN; i<MS_DECREASE_MAX; i++)
409     {
410         SpeedDecrease &slowdown = m_speed_decrease[i];
411         slowdown.update(ticks);
412         slowdown_factor = std::min(slowdown_factor,
413                                    slowdown.getSlowdownFraction());
414     }
415 
416     m_add_engine_force  = 0;
417     m_current_max_speed = m_kart->getKartProperties()->getEngineMaxSpeed();
418 
419     // Then add the speed increase from each category
420     // ----------------------------------------------
421     for(unsigned int i=MS_INCREASE_MIN; i<MS_INCREASE_MAX; i++)
422     {
423         SpeedIncrease &speedup = m_speed_increase[i];
424         speedup.update(ticks);
425         m_current_max_speed += speedup.getSpeedIncrease();
426         m_add_engine_force  += speedup.getEngineForce();
427     }
428     if (getSpeedIncreaseTicksLeft(MS_INCREASE_SKIDDING) > 0 &&
429         getSpeedIncreaseTicksLeft(MS_INCREASE_RED_SKIDDING) > 0)
430     {
431         SpeedIncrease &speedup = m_speed_increase[MS_INCREASE_SKIDDING];
432         m_current_max_speed -= speedup.getSpeedIncrease();
433         m_add_engine_force  -= speedup.getEngineForce();
434     }
435 
436     m_current_max_speed *= slowdown_factor;
437 
438     // Then cap the current speed of the kart
439     // --------------------------------------
440     if(m_min_speed > 0 && m_kart->getSpeed() < m_min_speed)
441     {
442         m_kart->getVehicle()->setMinSpeed(m_min_speed);
443     }
444     else
445         m_kart->getVehicle()->setMinSpeed(0);   // no additional acceleration
446 
447     if (m_kart->isOnGround())
448         m_kart->getVehicle()->setMaxSpeed(m_current_max_speed);
449     else
450         m_kart->getVehicle()->setMaxSpeed(9999.9f);
451 
452 }   // update
453 
454 // ----------------------------------------------------------------------------
455 /** Saves the speed data in a network string for rewind.
456  *  \param buffer Pointer to the network string to store the data.
457  */
saveState(BareNetworkString * buffer) const458 void MaxSpeed::saveState(BareNetworkString *buffer) const
459 {
460     // Save the slowdown states
461     // ------------------------
462     // Get the bit pattern of all active slowdowns
463     uint8_t active_slowdown = 0;
464     for(unsigned int i=MS_DECREASE_MIN, b=1; i<MS_DECREASE_MAX; i++, b <<=1)
465     {
466         // Don't bother saving terrain, this will get updated automatically
467         // each frame.
468         if(i==MS_DECREASE_TERRAIN) continue;
469         if (m_speed_decrease[i].isActive())
470             active_slowdown |= b;
471     }
472     buffer->addUInt8(active_slowdown);
473 
474     for(unsigned int i=MS_DECREASE_MIN, b=1; i<MS_DECREASE_MAX; i++, b <<= 1)
475     {
476         if (i == MS_DECREASE_TERRAIN)
477         {
478             // Handle in local state
479             continue;
480         }
481         else if (active_slowdown & b)
482             m_speed_decrease[i].saveState(buffer);
483     }
484 
485     // Now save the speedup state
486     // --------------------------
487     // Get the bit pattern of all active speedups
488     uint8_t active_speedups = 0;
489     for(unsigned int i=MS_INCREASE_MIN, b=1; i<MS_INCREASE_MAX; i++, b <<= 1)
490     {
491         if(m_speed_increase[i].isActive())
492             active_speedups |= b;
493     }
494     buffer->addUInt8(active_speedups);
495     for(unsigned int i=MS_INCREASE_MIN, b=1; i<MS_INCREASE_MAX; i++, b <<= 1)
496     {
497         if(active_speedups & b)
498             m_speed_increase[i].saveState(buffer);
499     }
500 
501 }   // saveState
502 
503 // ----------------------------------------------------------------------------
504 /** Restore a saved state.
505  *  \param buffer Saved state.
506  */
rewindTo(BareNetworkString * buffer)507 void MaxSpeed::rewindTo(BareNetworkString *buffer)
508 {
509     // Restore the slowdown states
510     // ---------------------------
511     // Get the bit pattern of all active slowdowns
512     uint8_t active_slowdown = buffer->getUInt8();
513 
514     for(unsigned int i=MS_DECREASE_MIN, b=1; i<MS_DECREASE_MAX; i++, b <<= 1)
515     {
516         if (i == MS_DECREASE_TERRAIN)
517         {
518             // Handle in local state
519             continue;
520         }
521         else
522             m_speed_decrease[i].rewindTo(buffer, (active_slowdown & b) == b);
523     }
524 
525     // Restore the speedup state
526     // --------------------------
527     // Get the bit pattern of all active speedups
528     uint8_t active_speedups = buffer->getUInt8();
529     for(unsigned int i=MS_INCREASE_MIN, b=1; i<MS_INCREASE_MAX; i++, b <<= 1)
530     {
531         m_speed_increase[i].rewindTo(buffer, (active_speedups & b) == b);
532     }
533     // Make sure to update the physics
534     update(0);
535 }   // rewindoTo
536 
537