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 #ifndef HEADER_MAX_SPEED_HPP
20 #define HEADER_MAX_SPEED_HPP
21 
22 #include "utils/types.hpp"
23 #include <limits>
24 
25 /** \defgroup karts */
26 
27 class AbstractKart;
28 class BareNetworkString;
29 
30 class MaxSpeed
31 {
32 friend class KartRewinder;
33 public:
34     /** The categories to use for increasing the speed of a kart:
35      *  Increase due to zipper, slipstream, nitro, rubber band,
36      *  skidding usage. */
37     enum  {MS_INCREASE_MIN,
38            MS_INCREASE_ZIPPER = MS_INCREASE_MIN,
39            MS_INCREASE_SLIPSTREAM,
40            MS_INCREASE_NITRO,
41            MS_INCREASE_RUBBER,
42            MS_INCREASE_SKIDDING,
43            MS_INCREASE_RED_SKIDDING,
44            MS_INCREASE_MAX};
45 
46     /** The categories to use for decreasing the speed of a kart:
47      *  Decrease due to terrain, different AI levels and end controller. */
48     enum {MS_DECREASE_MIN,
49           MS_DECREASE_TERRAIN = MS_DECREASE_MIN,
50           MS_DECREASE_AI,
51           MS_DECREASE_BUBBLE,
52           MS_DECREASE_SQUASH,
53           MS_DECREASE_MAX};
54 
55 private:
56     /** A pointer to the kart to which this speed handling object belongs. */
57     AbstractKart *m_kart;
58 
59     /** The current maximum speed. */
60     float m_current_max_speed;
61 
62     /** Additional engine force, summed from all SpeedIncrease engine forces. */
63     float m_add_engine_force;
64 
65     /** If >0 then the minimum speed a kart should have (used for zippers). */
66     float m_min_speed;
67 
68     // ------------------------------------------------------------------------
69     /** An internal class to store and handle speed increase related data. */
70     class SpeedIncrease
71     {
72     public:
73         /** The maximum additional speed allowed, 3 digits precision. */
74         uint16_t m_max_add_speed;
75         /** How long this speed will apply. This is used as a timer internally,
76          *  to the duration will be decreased. When the duration is <0, the
77          *  fade out time starts, and duration will go down to
78          *  -m_fade_out_time before this speed increase stops. */
79         int16_t m_duration;
80         /** The fadeout time. */
81         int16_t m_fade_out_time;
82         /** The current max speed increase value, updated with duration. */
83         float m_current_speedup;
84         /** Additional engine force, 1 digit precision. */
85         uint16_t m_engine_force;
86         /** The constructor initialised the values with a no-increase
87          *  entry, i.e. an entry that does affect top speed at all. */
SpeedIncrease()88         SpeedIncrease()
89         {
90             reset();
91         }   // SpeedIncrease
92         // --------------------------------------------------------------------
93         /** Resets this increase category to be not active. */
reset()94         void reset()
95         {
96             m_max_add_speed   = 0;
97             m_duration        = std::numeric_limits<int16_t>::min();
98             m_fade_out_time   = 0;
99             m_current_speedup = 0;
100             m_engine_force    = 0;
101         }   // reset
102         // --------------------------------------------------------------------
103         void update(int ticks);
104         void saveState(BareNetworkString *buffer) const;
105         void rewindTo(BareNetworkString *buffer, bool is_active);
106         // --------------------------------------------------------------------
107         /** Returns the current speedup for this category. */
getSpeedIncrease() const108         float getSpeedIncrease() const {return m_current_speedup;}
109         // --------------------------------------------------------------------
110         /** Returns the remaining time till the fade out time starts.
111          *  Note that this function will return a negative value if
112          *  the fade_out time has started or this speed increase has
113          *  expired. */
getTimeLeft() const114         int getTimeLeft() const      {return m_duration;       }
115         // --------------------------------------------------------------------
116         /** Returns the additional engine force for this speed increase. */
getEngineForce() const117         float getEngineForce() const
118         {
119             return m_duration > 0 ? (float)m_engine_force / 10.0f : 0;
120         }   // getEngineForce
121         // --------------------------------------------------------------------
122         /** Returns if this speed increase is active atm. */
isActive() const123         bool isActive() const { return m_duration > -m_fade_out_time; }
124     };   // SpeedIncrease
125 
126     // ------------------------------------------------------------------------
127     /** An internal class to store and handle speed decrease related data. */
128     class SpeedDecrease
129     {
130     public:
131         /** The maximum slowdown to apply, 3 digits precision. */
132         uint16_t m_max_speed_fraction;
133         /** The current slowdown fraction, taking the fade-in time
134          *  into account. */
135         float m_current_fraction;
136 
137         /** How long it should take for the full slowdown to take effect. */
138         int16_t m_fade_in_ticks;
139 
140         /** How long the effect should last. A -1 as value indicates
141          *  that this effect stays active till it is changed back. */
142         int16_t m_duration;
143 
144         /** The constructor initialises the data with data that won't
145          *  affect top speed at all. */
SpeedDecrease()146         SpeedDecrease()
147         {
148             reset();
149         }   // SpeedDecrease
150         // --------------------------------------------------------------------
151         /** Resets the state to be inactive. */
reset()152         void reset()
153         {
154             m_max_speed_fraction = 1000;
155             m_current_fraction   = 1.0f;
156             m_fade_in_ticks      = 0;
157             m_duration           = 0;
158         }   //reset
159         // --------------------------------------------------------------------
160         void update(int ticks);
161         void saveState(BareNetworkString *buffer) const;
162         void rewindTo(BareNetworkString *buffer, bool is_active);
163         // --------------------------------------------------------------------
164         /** Returns the current slowdown fracftion, taking a 'fade in'
165          *  into account. */
getSlowdownFraction() const166         float getSlowdownFraction() const        { return m_current_fraction; }
167         // --------------------------------------------------------------------
getTimeLeft() const168         int getTimeLeft() const                          { return m_duration; }
169         // --------------------------------------------------------------------
170         /** Returns if this speed decrease is active atm. A duration of
171          *  -1 indicates an ongoing effect. */
isActive() const172         bool isActive() const    { return m_duration > 0 || m_duration <= -1; }
173     };   // SpeedDecrease
174 
175     // ------------------------------------------------------------------------
176     /** Stores all speed decrease related information
177      *  for each possible category. */
178     SpeedDecrease  m_speed_decrease[MS_DECREASE_MAX];
179 
180     /** Stores all speed increase related information
181      *  for each possible category. */
182     SpeedIncrease  m_speed_increase[MS_INCREASE_MAX];
183 
184 
185 public:
186           MaxSpeed(AbstractKart *kart);
187 
188     void  increaseMaxSpeed(unsigned int category, float add_speed,
189                            float engine_force, int duration,
190                            int fade_out_time);
191     void  instantSpeedIncrease(unsigned int category,
192                                float add_speed, float speed_boost,
193                                float engine_force, int duration,
194                                int fade_out_time);
195     void  setSlowdown(unsigned int category, float max_speed_fraction,
196                       int fade_in_time, int duration=-1);
197     int   getSpeedIncreaseTicksLeft(unsigned int category);
198     int   isSpeedIncreaseActive(unsigned int category);
199     int   isSpeedDecreaseActive(unsigned int category);
200     void  update(int ticks);
201     void  reset();
202     void  saveState(BareNetworkString *buffer) const;
203     void  rewindTo(BareNetworkString *buffer);
204     // ------------------------------------------------------------------------
205     /** Sets the minimum speed a kart should have. This is used to guarantee
206      *  that e.g. zippers on ramps will always fast enough for the karts to
207      *  reach the other end. If set to a negative number, it will have
208      *  no effect. */
setMinSpeed(float s)209     void setMinSpeed(float s) { m_min_speed = s; }
210     // ------------------------------------------------------------------------
211     /** Returns the current maximum speed for this kart. */
getCurrentMaxSpeed() const212     float getCurrentMaxSpeed() const { return m_current_max_speed; }
213     // ------------------------------------------------------------------------
214     /** Returns the additional engine force. */
getCurrentAdditionalEngineForce() const215     float getCurrentAdditionalEngineForce() const { return m_add_engine_force;}
216 };   // MaxSpeed
217 #endif
218