1 //  SuperTuxKart - a fun racing game with go-kart
2 //  Copyright (C) 2004-2015 SuperTuxKart-Team
3 //
4 //  This program is free software; you can redistribute it and/or
5 //  modify it under the terms of the GNU General Public License
6 //  as published by the Free Software Foundation; either version 3
7 //  of the License, or (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program; if not, write to the Free Software
16 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 
18 #ifndef HEADER_LINEAR_WORLD_HPP
19 #define HEADER_LINEAR_WORLD_HPP
20 
21 #include "modes/world_with_rank.hpp"
22 #include "utils/aligned_array.hpp"
23 
24 #include <climits>
25 #include <vector>
26 
27 class SFXBase;
28 
29 /*
30  * A 'linear world' is a subcategory of world used in 'standard' races, i.e.
31  * with a start line and a road that loops. This includes management of drivelines
32  * and lap counting.
33  * \ingroup modes
34  */
35 class LinearWorld : public WorldWithRank
36 {
37 private:
38     /** Sfx for the final lap. */
39     SFXBase     *m_last_lap_sfx;
40 
41     /** Last lap sfx should only be played once. */
42     bool         m_last_lap_sfx_played;
43 
44     bool         m_last_lap_sfx_playing;
45 
46     /** True if clients and server has the same check structure. */
47     bool         m_check_structure_compatible;
48 
49     /** The fastest lap time, in ticks of physics dt. */
50     int          m_fastest_lap_ticks;
51 
52     core::stringw m_fastest_lap_kart_name;
53 
54     /** The track length returned by Track::getLength() only covers the
55      *  distance from start line to finish line, i.e. it does not include
56      *  the distance the karts actually start behind the start line (the
57      *  karts would have a negative distance till they reach the start line
58      *  for the first time). This values stores the additional distance by
59      *  which the track length must be increased, which is important to
60      *  get valid finish times estimates. */
61     float       m_distance_increase;
62 
63     /** This stores the live time difference between a ghost kart
64      *  and a second kart racing against it (normal or ghost).
65      */
66     float       m_live_time_difference;
67 
68     /** True if the live_time_difference is invalid */
69     bool        m_valid_reference_time;
70 
71     /* if set then the game will auto end after this time for networking */
72     float       m_finish_timeout;
73 
74     /** This calculate the time difference between the second kart in the race
75      *  (there must be at least two) and the first kart in the race
76      *  (who must be a ghost).
77      */
78     void  updateLiveDifference();
79 
80     // ------------------------------------------------------------------------
81     /** Some additional info that needs to be kept for each kart
82      * in this kind of race.
83      */
84     class KartInfo
85     {
86     public:
87         /** Number of finished laps. */
88         int         m_finished_laps;
89 
90         /** Time at finishing last lap. */
91         int         m_ticks_at_last_lap;
92 
93         /** Time at start of a new lap. */
94         int         m_lap_start_ticks;
95 
96         /** During last lap only: estimated finishing time!   */
97         float       m_estimated_finish;
98 
99         /** How far the kart has travelled (this is (number-of-laps-1) times
100          *  track-length plus distance-along-track). */
101         float       m_overall_distance;
102 
103         /** Accumulates the time a kart has been driving in the wrong
104          *  direction so that a message can be displayed. */
105         float       m_wrong_way_timer;
106 
107         /** Initialises all fields. */
KartInfo()108         KartInfo()  { reset(); }
109         // --------------------------------------------------------------------
110         /** Re-initialises all data. */
reset()111         void reset()
112         {
113             m_finished_laps     = -1;
114             m_lap_start_ticks   = 0;
115             m_ticks_at_last_lap = INT_MAX;
116             m_estimated_finish  = -1.0f;
117             m_overall_distance  = 0.0f;
118             m_wrong_way_timer   = 0.0f;
119         }   // reset
120         // --------------------------------------------------------------------
121         void saveCompleteState(BareNetworkString* bns);
122         // --------------------------------------------------------------------
123         void restoreCompleteState(const BareNetworkString& b);
124     };
125     // ------------------------------------------------------------------------
126 
127 protected:
128 
129     /** This vector contains an 'KartInfo' struct for every kart in the race.
130       * This member is not strictly private but try not to use it directly outside
131       * tightly related classes (e.g. AI)
132       */
133     std::vector<KartInfo> m_kart_info;
134 
135     virtual void  checkForWrongDirection(unsigned int i, float dt);
136     virtual float estimateFinishTimeForKart(AbstractKart* kart) OVERRIDE;
137 
138 public:
139                   LinearWorld();
140    /** call just after instanciating. can't be moved to the contructor as child
141        classes must be instanciated, otherwise polymorphism will fail and the
142        results will be incorrect */
143     virtual void  init() OVERRIDE;
144     virtual      ~LinearWorld();
145 
146     virtual void  update(int ticks) OVERRIDE;
147     virtual void  updateGraphics(float dt) OVERRIDE;
148     float         getDistanceDownTrackForKart(const int kart_id,
149                                             bool account_for_checklines) const;
150     void          updateTrackSectors();
151     void          updateRacePosition();
152     float         getDistanceToCenterForKart(const int kart_id) const;
153     float         getEstimatedFinishTime(const int kart_id) const;
154     int           getLapForKart(const int kart_id) const;
155     int           getTicksAtLapForKart(const int kart_id) const;
getLiveTimeDifference() const156     float         getLiveTimeDifference() const { return m_live_time_difference; }
hasValidTimeDifference() const157     bool          hasValidTimeDifference() const { return m_valid_reference_time; }
158 
159     virtual  void getKartsDisplayInfo(
160                   std::vector<RaceGUIBase::KartIconDisplayInfo> *info) OVERRIDE;
161 
162     virtual unsigned int getNumberOfRescuePositions() const OVERRIDE;
163     virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE;
164     virtual btTransform getRescueTransform(unsigned int index) const OVERRIDE;
165     virtual void  reset(bool restart=false) OVERRIDE;
166     virtual void  newLap(unsigned int kart_index) OVERRIDE;
167 
168     // ------------------------------------------------------------------------
169     /** Returns if this race mode has laps. */
raceHasLaps()170     virtual bool  raceHasLaps() OVERRIDE { return true; }
171     // ------------------------------------------------------------------------
172     /** Returns if this race mode has bonus items. */
haveBonusBoxes()173     virtual bool  haveBonusBoxes() OVERRIDE { return true; }
174     // ------------------------------------------------------------------------
175     /** Override settings from base class */
useChecklineRequirements() const176     virtual bool useChecklineRequirements() const OVERRIDE { return true; }
177     // ------------------------------------------------------------------------
178     /** Returns the number of laps a kart has completed.
179      *  \param kart_index World index of the kart. */
getFinishedLapsOfKart(unsigned int kart_index) const180     int getFinishedLapsOfKart(unsigned int kart_index) const OVERRIDE
181     {
182         assert(kart_index < m_kart_info.size());
183         return m_kart_info[kart_index].m_finished_laps;
184     }   // getkartLap
185     // ------------------------------------------------------------------------
186     void setLastTriggeredCheckline(unsigned int kart_index, int index);
187     // ------------------------------------------------------------------------
188     /** Returns how far the kart has driven so far (i.e.
189      *  number-of-laps-finished times track-length plus distance-on-track.
190      *  \param kart_index World kart id of the kart. */
getOverallDistance(unsigned int kart_index) const191     float getOverallDistance(unsigned int kart_index) const
192     {
193         return m_kart_info[kart_index].m_overall_distance;
194     }   // getOverallDistance
195     // ------------------------------------------------------------------------
196     /** Returns time for the fastest laps */
getFastestLap() const197     float getFastestLap() const
198     {
199         return stk_config->ticks2Time(m_fastest_lap_ticks);
200     }
201     // ------------------------------------------------------------------------
202     /** Returns the kart name that made the fastest lap time */
getFastestLapKartName() const203     stringw getFastestLapKartName() const
204     {
205         return m_fastest_lap_kart_name;
206     }
207     // ------------------------------------------------------------------------
208     /** Network use: get fastest lap in ticks */
getFastestLapTicks() const209     int getFastestLapTicks() const
210     {
211         return m_fastest_lap_ticks;
212     }
213     // ------------------------------------------------------------------------
214     /** Network use: set fastest lap in ticks */
setFastestLapTicks(int ticks)215     void setFastestLapTicks(int ticks)
216     {
217         m_fastest_lap_ticks = ticks;
218     }
219     // ------------------------------------------------------------------------
220     /** Network use: set fastest kart name */
setFastestKartName(const stringw & name)221     void setFastestKartName(const stringw& name)
222     {
223         m_fastest_lap_kart_name = name;
224     }
225     // ------------------------------------------------------------------------
226     virtual std::pair<uint32_t, uint32_t> getGameStartedProgress() const
227         OVERRIDE;
228     // ------------------------------------------------------------------------
229     virtual void saveCompleteState(BareNetworkString* bns,
230                                    STKPeer* peer) OVERRIDE;
231     // ------------------------------------------------------------------------
232     virtual void restoreCompleteState(const BareNetworkString& b) OVERRIDE;
233     // ------------------------------------------------------------------------
234     void updateCheckLinesServer(int check_id, int kart_id);
235     // ------------------------------------------------------------------------
236     void updateCheckLinesClient(const BareNetworkString& b);
237     // ------------------------------------------------------------------------
238     void handleServerCheckStructureCount(unsigned count);
239 };   // LinearWorld
240 
241 #endif
242