1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2006-2015 SuperTuxKart-Team
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_RACEMANAGER_HPP
20 #define HEADER_RACEMANAGER_HPP
21 
22 /**
23   * \defgroup race
24   * Contains the race information that is conceptually above what you can find
25   * in group Modes. Handles highscores, grands prix, number of karts, which
26   * track was selected, etc.
27   */
28 
29 #include <vector>
30 #include <algorithm>
31 #include <string>
32 
33 #include "network/remote_kart_info.hpp"
34 #include "race/grand_prix_data.hpp"
35 #include "utils/vec3.hpp"
36 
37 class AbstractKart;
38 class NetworkString;
39 class SavedGrandPrix;
40 class Track;
41 
42 static const std::string IDENT_STD      ("STANDARD"        );
43 static const std::string IDENT_TTRIAL   ("STD_TIMETRIAL"   );
44 static const std::string IDENT_FTL      ("FOLLOW_LEADER"   );
45 static const std::string IDENT_STRIKES  ("BATTLE_3_STRIKES");
46 static const std::string IDENT_FFA      ("BATTLE_FFA"      );
47 static const std::string IDENT_CTF      ("BATTLE_CTF"      );
48 static const std::string IDENT_EASTER   ("EASTER_EGG_HUNT" );
49 static const std::string IDENT_SOCCER   ("SOCCER"          );
50 static const std::string IDENT_GHOST    ("GHOST"           );
51 static const std::string IDENT_OVERWORLD("OVERWORLD"       );
52 static const std::string IDENT_CUTSCENE ("CUTSCENE"        );
53 
54 /**
55  * The race manager has two functions:
56  *  1) it stores information about the race the user selected (e.g. number
57  *     of karts, track, race mode etc.). Most of the values are just stored
58  *     from the menus, and just read back, except for GP mode (the race
59  *     manager stores the GP information, but World queries only track
60  *     and number of laps, so in case of GP this information is taken from
61  *     the GrandPrix object), and local player information (number of local
62  *     players, and selected karts).
63  *     Information about player karts (which player selected which kart,
64  *     player ids) is stored in a RemoteKartInfo structure and used later
65  *     to initialise the KartStatus array (startNew()). The KartStatus array
66  *     stores information about all karts (player and AI), and is used to
67  *     determine the order in which karts are started (see startNextRace()).
68  *  2) when a race is started, it creates the world, and keeps track of
69  *     score during the race. When a race is finished, it deletes the world,
70  *     and (depending on race mode) starts the next race by creating a new
71  *     world.
72  *  Information in the RaceManager is considered to be 'more static', sometimes
73  *  the world has similar functions showing the current state. E.g.: the
74  *  race manager keeps track of the number of karts with which the race was
75  *  started, while world keeps track of the number of karts currently in the
76  *  race (consider a race mode like follow the leader where karts can get
77  *  eliminated, but still the RaceManager has to accumulate points for those
78  *  karts).
79  *  The race manager handles all race types as a kind of grand prix. E.g.:
80  *  a quick race is basically a GP with only one track (so the race manager
81  *  keeps track of scores even though no scores are used in a quick race).
82  *
83  * \ingroup race
84  */
85 class RaceManager
86 {
87 public:
88     /** The major types or races supported in STK
89     */
90     enum MajorRaceModeType
91     {
92         MAJOR_MODE_GRAND_PRIX = 0,
93         MAJOR_MODE_SINGLE
94     };
95 
96     // quick method to tell the difference between battle modes and race modes
97     // think of it like a bitmask, but done in decimal to avoid endianness
98     // issues
99 #define LINEAR_RACE(ID, COUNT_LAPSES) (1000+ID+100*COUNT_LAPSES)
100 #define BATTLE_ARENA(ID) (2000+ID)
101 #define EASTER_EGG(ID)   (3000+ID)
102 #define MISC(ID)         (4000+ID)
103 
104     // ----------------------------------------------------------------------------------------
105     /** Minor variants to the major types of race.
106      *  Make sure to use the 'LINEAR_RACE/BATTLE_ARENA' macros. */
107     enum MinorRaceModeType
108     {
109         MINOR_MODE_NONE             = -1,
110 
111         MINOR_MODE_NORMAL_RACE      = LINEAR_RACE(0, true),
112         MINOR_MODE_TIME_TRIAL       = LINEAR_RACE(1, true),
113         MINOR_MODE_FOLLOW_LEADER    = LINEAR_RACE(2, false),
114 
115         MINOR_MODE_3_STRIKES        = BATTLE_ARENA(0),
116         MINOR_MODE_FREE_FOR_ALL     = BATTLE_ARENA(1),
117         MINOR_MODE_CAPTURE_THE_FLAG = BATTLE_ARENA(2),
118         MINOR_MODE_SOCCER           = BATTLE_ARENA(3),
119 
120         MINOR_MODE_EASTER_EGG       = EASTER_EGG(0),
121 
122         MINOR_MODE_OVERWORLD        = MISC(0),
123         MINOR_MODE_TUTORIAL         = MISC(1),
124         MINOR_MODE_CUTSCENE         = MISC(2)
125     };
126 
127     // ----------------------------------------------------------------------------------------
128     /** True if the AI should have additional abbilities, e.g.
129      *  nolok will get special bubble gums in the final challenge. */
130     enum AISuperPower
131     {
132         SUPERPOWER_NONE       = 0,
133         SUPERPOWER_NOLOK_BOSS = 1
134     };
135 
136     // ----------------------------------------------------------------------------------------
137     /** Returns a string identifier for each minor race mode.
138      *  \param mode Minor race mode.
139      */
getIdentOf(const MinorRaceModeType mode)140     static const std::string& getIdentOf(const MinorRaceModeType mode)
141     {
142         switch (mode)
143         {
144             case MINOR_MODE_NORMAL_RACE:      return IDENT_STD;
145             case MINOR_MODE_TIME_TRIAL:       return IDENT_TTRIAL;
146             case MINOR_MODE_FOLLOW_LEADER:    return IDENT_FTL;
147             case MINOR_MODE_3_STRIKES:        return IDENT_STRIKES;
148             case MINOR_MODE_FREE_FOR_ALL:     return IDENT_FFA;
149             case MINOR_MODE_CAPTURE_THE_FLAG: return IDENT_CTF;
150             case MINOR_MODE_EASTER_EGG:       return IDENT_EASTER;
151             case MINOR_MODE_SOCCER:           return IDENT_SOCCER;
152             default: assert(false);
153                      return IDENT_STD;  // stop compiler warning
154         }
155     }   // getIdentOf
156 
157     // ----------------------------------------------------------------------------------------
158     /** Returns the icon for a minor race mode.
159      *  \param mode Minor race mode.
160      */
getIconOf(const MinorRaceModeType mode)161     static const char* getIconOf(const MinorRaceModeType mode)
162     {
163         switch (mode)
164         {
165             case MINOR_MODE_NORMAL_RACE:    return "/gui/icons/mode_normal.png";
166             case MINOR_MODE_TIME_TRIAL:     return "/gui/icons/mode_tt.png";
167             case MINOR_MODE_FOLLOW_LEADER:  return "/gui/icons/mode_ftl.png";
168             case MINOR_MODE_3_STRIKES:      return "/gui/icons/mode_3strikes.png";
169             case MINOR_MODE_FREE_FOR_ALL:   return "/gui/icons/mode_weapons.png";
170             case MINOR_MODE_CAPTURE_THE_FLAG: return "/gui/icons/mode_weapons.png";
171             case MINOR_MODE_EASTER_EGG:     return "/gui/icons/mode_easter.png";
172             case MINOR_MODE_SOCCER:         return "/gui/icons/mode_soccer.png";
173             default: assert(false); return NULL;
174         }
175     }   // getIconOf
176 
177     // ----------------------------------------------------------------------------------------
178     static const core::stringw getNameOf(const MinorRaceModeType mode);
179     // ----------------------------------------------------------------------------------------
180     /** Returns if the currently set minor game mode can be used by the AI. */
hasAI()181     bool hasAI()
182     {
183         switch (m_minor_mode)
184         {
185             case MINOR_MODE_NORMAL_RACE:    return true;
186             case MINOR_MODE_TIME_TRIAL:     return true;
187             case MINOR_MODE_FOLLOW_LEADER:  return true;
188             case MINOR_MODE_3_STRIKES:      return true;
189             case MINOR_MODE_FREE_FOR_ALL:   return false;
190             case MINOR_MODE_CAPTURE_THE_FLAG: return false;
191             case MINOR_MODE_EASTER_EGG:     return false;
192             case MINOR_MODE_SOCCER:         return true;
193             default: assert(false);         return false;
194         }
195     }   // hasAI
196 
197 
198     // ----------------------------------------------------------------------------------------
199     /** Returns the minor mode id from a string identifier. This function is
200      *  used from challenge_data, which reads the mode from a challenge file.
201      *  \param name The name of the minor mode.
202      */
getModeIDFromInternalName(const std::string & name)203     static const MinorRaceModeType getModeIDFromInternalName(
204                                                        const std::string &name)
205     {
206         if      (name==IDENT_STD    ) return MINOR_MODE_NORMAL_RACE;
207         else if (name==IDENT_TTRIAL ) return MINOR_MODE_TIME_TRIAL;
208         else if (name==IDENT_FTL    ) return MINOR_MODE_FOLLOW_LEADER;
209         else if (name==IDENT_STRIKES) return MINOR_MODE_3_STRIKES;
210         else if (name==IDENT_FFA)     return MINOR_MODE_FREE_FOR_ALL;
211         else if (name==IDENT_CTF)     return MINOR_MODE_CAPTURE_THE_FLAG;
212         else if (name==IDENT_EASTER ) return MINOR_MODE_EASTER_EGG;
213         else if (name==IDENT_SOCCER)  return MINOR_MODE_SOCCER;
214 
215         assert(0);
216         return MINOR_MODE_NONE;
217     }
218 
219 #undef LINEAR_RACE
220 #undef BATTLE_ARENA
221 #undef MISC
222 
223     /** Game difficulty. */
224     enum Difficulty     { DIFFICULTY_EASY = 0,
225                           DIFFICULTY_FIRST = DIFFICULTY_EASY,
226                           DIFFICULTY_MEDIUM,
227                           DIFFICULTY_HARD,
228                           DIFFICULTY_BEST,
229                           DIFFICULTY_LAST = DIFFICULTY_BEST,
230                           DIFFICULTY_COUNT,
231                           DIFFICULTY_NONE};
232 
233     /** Different kart types: A local player, a player connected via network,
234      *  an AI kart, the leader kart (currently not used), a ghost kart and
235      *  spare tire karts which allow gain life in battle mode */
236     enum KartType       { KT_PLAYER, KT_NETWORK_PLAYER, KT_AI, KT_LEADER,
237                           KT_GHOST, KT_SPARE_TIRE };
238 private:
239 
240     bool m_started_from_overworld;
241 
242 public:
243 
244     /** This data structure accumulates kart data and race result data from
245      *  each race. */
246     struct KartStatus
247     {
248         /** The kart identifier. */
249         std::string m_ident;
250         /** For networked karts. */
251         std::string m_player_name;
252         // Score for this kart. */
253         int         m_score;
254         /** Needed for restart race, and for race results GUI. */
255         int         m_last_score;
256         /** Sum of times of all races. */
257         float       m_overall_time;
258         /** Needed for restart. */
259         float       m_last_time;
260         /** Kart type: AI, player, network player etc. */
261         KartType    m_kart_type;
262         /** Player controling the kart, for AI: -1 */
263         int         m_local_player_id;
264         /** Global ID of player. */
265         int         m_global_player_id;
266         /** In GPs, at the end, will hold the overall rank of this kart
267          *  (0<=m_gp_rank < num_karts-1). */
268         int         m_gp_rank;
269         /** Boosted status (AI only). */
270         bool        m_boosted_ai;
271         /** The handicap for this player. */
272         HandicapLevel m_handicap;
273         /** Kart color of player (used in gp win / lose screen). */
274         float       m_color;
KartStatusRaceManager::KartStatus275         KartStatus(const std::string& ident, const int& prev_finish_pos,
276                    int local_player_id, int global_player_id,
277                    int init_gp_rank, KartType kt,
278                    HandicapLevel handicap) :
279                    m_ident(ident), m_score(0), m_last_score(0),
280                    m_overall_time(0.0f), m_last_time(0.0f),
281                    m_kart_type(kt),
282                    m_local_player_id(local_player_id),
283                    m_global_player_id(global_player_id),
284                    m_gp_rank(init_gp_rank), m_handicap(handicap)
285                 { m_boosted_ai = false; m_color = 0.0f; }
286 
287     };   // KartStatus
288 private:
289 
290     /** The kart status data for each kart. */
291     std::vector<KartStatus>          m_kart_status;
292 
293     /** The selected difficulty. */
294     Difficulty                       m_difficulty;
295 
296     /** The major mode (single race, GP). */
297     MajorRaceModeType                m_major_mode;
298 
299     /** The minor mode (race, time trial, ftl, battle mode). */
300     MinorRaceModeType                m_minor_mode;
301     /** Stores remote kart information about all player karts. */
302     std::vector<RemoteKartInfo>      m_player_karts;
303     std::vector<std::string>         m_tracks;
304 
305     /** Number of local players. */
306     unsigned int m_num_local_players;
307 
308     /** The number of laps for each track of a GP (only one element
309      *  is used if only a single track is used. */
310     std::vector<int>                 m_num_laps;
311 
312     /** Whether a track should be reversed */
313     std::vector<bool>                m_reverse_track;
314 
315     /** The list of default AI karts to use. This is from the command line. */
316     std::vector<std::string>         m_default_ai_list;
317 
318     /** If set, specifies which kart to use for AI(s) */
319     std::string                      m_ai_kart_override;
320 
321     AISuperPower                     m_ai_superpower;
322 
323     /** The list of AI karts to use. This is stored here so that the
324      *  same list of AIs is used for all tracks of a GP. */
325     std::vector<std::string>         m_ai_kart_list;
326     int                              m_track_number;
327     GrandPrixData                    m_grand_prix;
328     SavedGrandPrix*                  m_saved_gp;
329     int                              m_num_karts;
330     unsigned int                     m_num_red_ai;
331     unsigned int                     m_num_blue_ai;
332     unsigned int                     m_num_ghost_karts;
333     unsigned int                     m_num_spare_tire_karts;
334     unsigned int                     m_num_finished_karts;
335     unsigned int                     m_num_finished_players;
336     unsigned                         m_flag_return_ticks;
337     unsigned                         m_flag_deactivated_ticks;
338     int                              m_coin_target;
339     float                            m_time_target;
340     int                              m_goal_target;
341     int                              m_hit_capture_limit;
342     void startNextRace();    // start a next race
343 
operator <(const KartStatus & left,const KartStatus & right)344     friend bool operator< (const KartStatus& left, const KartStatus& right)
345     {
346         return (left.m_score < right.m_score) ||
347             (left.m_score == right.m_score &&
348              left.m_overall_time > right.m_overall_time);
349     }
350 
351     bool m_have_kart_last_position_on_overworld;
352     Vec3 m_kart_last_position_on_overworld;
353 
354     /** Determines if saved GP should be continued or not*/
355     bool m_continue_saved_gp;
356 
357     bool m_is_recording_race;
358 
359     bool m_has_ghost_karts;
360 
361     bool m_watching_replay;
362 public:
363     // ----------------------------------------------------------------------------------------
364     static RaceManager* get();
365     // ----------------------------------------------------------------------------------------
366     static void create();
367     // ----------------------------------------------------------------------------------------
368     static void destroy();
369     // ----------------------------------------------------------------------------------------
370     static void clear();
371     // ----------------------------------------------------------------------------------------
372          RaceManager();
373         ~RaceManager();
374 
375     void reset();
376     void setPlayerKart(unsigned int player_id, const std::string &kart_name);
377     void setPlayerKart(unsigned int player_id,
378                        const RemoteKartInfo& ki);
379 
380     /** Sets additional information for a player to indicate which team it belong to
381     */
382     void setKartTeam(unsigned int player_id, KartTeam team);
383 
384     /** Sets the handicap for a player.
385      */
386     void setPlayerHandicap(unsigned int player_id, HandicapLevel handicap);
387 
388     /** In case of non GP mode set the track to use.
389      *  \param track Pointer to the track to use.
390      */
391     void setTrack(const std::string& track);
392 
393     /** \brief Returns the kart with a given GP rank (or NULL if no such
394      *  kart exists).
395      *  \param n Rank (0<=n<num_karts) to look for.
396      */
397     const AbstractKart* getKartWithGPRank(unsigned int n);
398 
399     /** \return the GP rank of a local player, or -1 if the given player ID
400      *  doesn't exist */
401     int getLocalPlayerGPRank(const int playerID) const;
402 
403 
404     /** Sort karts and update the m_gp_rank KartStatus member, in preparation
405       * for future calls to RaceManager::getKartGPRank or
406       *  RaceManager::getKartWithGPRank
407       */
408     void computeGPRanks();
409 
410     /** \brief Sets the difficulty.
411       * \param diff Difficulty.
412       */
413     void setDifficulty(Difficulty diff);
414     static Difficulty convertDifficulty(const std::string &difficulty);
415     void startNew(bool from_overworld);
416     void next();
417     void rerunRace();
418     void exitRace(bool delete_world=true);
419     void startGP(const GrandPrixData &gp, bool from_overworld,
420                  bool continue_saved_gp);
421     void saveGP();
422     void startSingleRace(const std::string &track_ident, const int num_laps,
423                           bool from_overworld);
424     void startWatchingReplay(const std::string &track_ident, const int num_laps);
425     void setupPlayerKartInfo();
426     void kartFinishedRace(const AbstractKart* kart, float time);
427     void setNumPlayers(int players, int local_players=-1);
428     void setDefaultAIKartList(const std::vector<std::string> &ai_list);
429     void computeRandomKartList();
430 
431     // ----------------------------------------------------------------------------------------
hasTimeTarget() const432     bool hasTimeTarget() const { return m_time_target > 0.0f; }
433     // ----------------------------------------------------------------------------------------
setMaxGoal(int max_goal)434     void setMaxGoal(int max_goal)
435     {
436         m_time_target = 0.0f;
437         m_goal_target = max_goal;
438     }   // setMaxGoal
439     // ----------------------------------------------------------------------------------------
getMaxGoal()440     int getMaxGoal(){ return m_goal_target; }
441     // ----------------------------------------------------------------------------------------
setCoinTarget(int num)442     void setCoinTarget(int num)   { m_coin_target = num; }
443     // ----------------------------------------------------------------------------------------
setGrandPrix(const GrandPrixData & gp)444     void setGrandPrix(const GrandPrixData &gp)
445     {
446         m_grand_prix = gp;
447         setCoinTarget(0);
448     }   // setGrandPrix
449     // ----------------------------------------------------------------------------------------
setAIKartOverride(const std::string & kart)450     void setAIKartOverride(const std::string& kart)
451     {
452         m_ai_kart_override = kart;
453     }   // setAIKartOverride
454     // ----------------------------------------------------------------------------------------
setAISuperPower(AISuperPower superpower)455     void setAISuperPower(AISuperPower superpower)
456     {
457         m_ai_superpower = superpower;
458     }   // setAISuperPower
459     // ----------------------------------------------------------------------------------------
getAISuperPower() const460     AISuperPower getAISuperPower() const { return m_ai_superpower; }
461     // ----------------------------------------------------------------------------------------
setNumLaps(int num)462     void setNumLaps(int num)
463     {
464         m_num_laps.clear();
465         m_num_laps.push_back(num);
466     }   // setNumLaps
467     // ----------------------------------------------------------------------------------------
setReverseTrack(bool r_t)468     void setReverseTrack(bool r_t)
469     {
470         m_reverse_track.clear();
471         m_reverse_track.push_back(r_t);
472     }   // setReverseTrack
473     // ----------------------------------------------------------------------------------------
setMajorMode(MajorRaceModeType mode)474     void setMajorMode(MajorRaceModeType mode) { m_major_mode = mode; }
475     // ----------------------------------------------------------------------------------------
setMinorMode(MinorRaceModeType mode)476     void setMinorMode(MinorRaceModeType mode)
477     {
478         m_minor_mode = mode;
479     }   // setMinorMode
480     // ----------------------------------------------------------------------------------------
setNumKarts(int num)481     void setNumKarts(int num)
482     {
483         m_num_karts = num;
484         m_ai_kart_override = "";
485         m_ai_superpower = SUPERPOWER_NONE;
486     }   // setNumKarts
487     // ----------------------------------------------------------------------------------------
setNumRedAI(unsigned int num)488     void setNumRedAI(unsigned int num)
489     {
490         m_num_red_ai = num;
491     }   // setNumRedAI
492     // ----------------------------------------------------------------------------------------
setNumBlueAI(unsigned int num)493     void setNumBlueAI(unsigned int num)
494     {
495         m_num_blue_ai = num;
496     }   // setNumBlueAI
497     // ----------------------------------------------------------------------------------------
setTimeTarget(float time)498     void setTimeTarget(float time)
499     {
500         m_goal_target = 0;
501         m_time_target = time;
502     }   // setTimeTarget
503     // ----------------------------------------------------------------------------------------
getKartInfo(unsigned int n)504     RemoteKartInfo& getKartInfo(unsigned int n)
505     {
506         return m_player_karts[n];
507     }   // getKartInfo
508     // ----------------------------------------------------------------------------------------
getNumLocalPlayers() const509     unsigned int getNumLocalPlayers() const
510     {
511         return m_num_local_players;
512     }   // getNumLocalPlayers
513 
514     // ----------------------------------------------------------------------------------------
515     /** Returns true if the split screen display leaves an empty space that
516      *  can be used to display the minimap.
517      */
getIfEmptyScreenSpaceExists() const518     bool getIfEmptyScreenSpaceExists() const
519     {
520         const float sqrt_num_players = sqrtf((float)getNumLocalPlayers());
521         const int rows = (int)ceil(sqrt_num_players);
522         const int cols = (int)round(sqrt_num_players);
523         const int total_spaces = rows * cols;
524         return (total_spaces - getNumLocalPlayers() > 0);
525     }   // getIfEmptyScreenSpaceExists
526     // ----------------------------------------------------------------------------------------
527     /** Returns the selected number of karts (selected number of players and
528      *  AI karts. */
getNumberOfKarts() const529     unsigned int getNumberOfKarts() const { return m_num_karts; }
530     // ----------------------------------------------------------------------------------------
getNumberOfAIKarts() const531     unsigned int getNumberOfAIKarts() const
532     {
533         return (unsigned int)m_ai_kart_list.size();
534     }   // getNumberOfAIKarts
535     // ----------------------------------------------------------------------------------------
getNumberOfRedAIKarts() const536     unsigned int getNumberOfRedAIKarts() const { return m_num_red_ai; }
537     // ----------------------------------------------------------------------------------------
getNumberOfBlueAIKarts() const538     unsigned int getNumberOfBlueAIKarts() const { return m_num_blue_ai; }
539     // ----------------------------------------------------------------------------------------
getNumNonGhostKarts() const540     unsigned int getNumNonGhostKarts() const
541                                     { return m_num_karts - m_num_ghost_karts; }
542     // ----------------------------------------------------------------------------------------
getMajorMode() const543     MajorRaceModeType getMajorMode() const { return m_major_mode; }
544     // ----------------------------------------------------------------------------------------
getMinorMode() const545     MinorRaceModeType getMinorMode() const { return m_minor_mode; }
546     // ----------------------------------------------------------------------------------------
getMinorModeName() const547     std::string getMinorModeName() const
548     {
549         switch (m_minor_mode)
550         {
551             case MINOR_MODE_NORMAL_RACE:    return "normal";
552             case MINOR_MODE_TIME_TRIAL:     return "time-trial";
553             case MINOR_MODE_FOLLOW_LEADER:  return "follow-the-leader";
554             case MINOR_MODE_3_STRIKES:      return "battle";
555             case MINOR_MODE_FREE_FOR_ALL:   return "ffa";
556             case MINOR_MODE_CAPTURE_THE_FLAG: return "ctf";
557             case MINOR_MODE_EASTER_EGG:     return "egg-hunt";
558             case MINOR_MODE_SOCCER:         return "soccer";
559             default: assert(false);         return "";
560         }
561     }
562     // ----------------------------------------------------------------------------------------
getNumPlayers() const563     unsigned int getNumPlayers() const
564     {
565         return (unsigned int) m_player_karts.size();
566     }   // getNumPlayers
567     // ----------------------------------------------------------------------------------------
568     /** \brief Returns the number lf laps.
569      *  In case of FTL or battle mode always return 9999, since they don't
570      *  have laps. This avoids problems in FTL GP, since in this case no laps
571      *  would be set (otherwise we would need many more tests in calls to
572      *  getNumLaps).
573      */
getNumLaps() const574     int getNumLaps() const
575     {
576         if(modeHasLaps())
577             return m_num_laps[m_track_number];
578         // else
579         return 9999;
580     }   // getNumLaps
581     // ----------------------------------------------------------------------------------------
582     /** \return whether the track should be reversed */
getReverseTrack() const583     bool getReverseTrack() const { return m_reverse_track[m_track_number]; }
584     // ----------------------------------------------------------------------------------------
585     /** Returns the difficulty. */
getDifficulty() const586     Difficulty getDifficulty() const { return m_difficulty; }
587     // ----------------------------------------------------------------------------------------
588     /** Returns the specified difficulty as a string. */
getDifficultyAsString(Difficulty diff) const589     std::string getDifficultyAsString(Difficulty diff) const
590     {
591         switch(diff)
592         {
593         case RaceManager::DIFFICULTY_EASY:   return "easy";   break;
594         case RaceManager::DIFFICULTY_MEDIUM: return "medium"; break;
595         case RaceManager::DIFFICULTY_HARD:   return "hard";   break;
596         case RaceManager::DIFFICULTY_BEST:   return "best";   break;
597         default:  assert(false);
598         }
599         return "";
600     }   // getDifficultyAsString
601 
602     // ----------------------------------------------------------------------------------------
603     core::stringw getDifficultyName(Difficulty diff) const;
604     // ----------------------------------------------------------------------------------------
getTrackName() const605     const std::string& getTrackName() const { return m_tracks[m_track_number];}
606     // ----------------------------------------------------------------------------------------
getGrandPrix() const607     const GrandPrixData& getGrandPrix() const { return m_grand_prix; }
608     // ----------------------------------------------------------------------------------------
getFinishedKarts() const609     unsigned int getFinishedKarts() const { return m_num_finished_karts; }
610     // ----------------------------------------------------------------------------------------
getFinishedPlayers() const611     unsigned int getFinishedPlayers() const { return m_num_finished_players; }
612     // ----------------------------------------------------------------------------------------
getKartGPRank(const int kart_id) const613     int getKartGPRank(const int kart_id)const
614     {
615         return m_kart_status[kart_id].m_gp_rank;
616     }   // getKartGPRank
617     // ----------------------------------------------------------------------------------------
getKartIdent(int kart) const618     const std::string& getKartIdent(int kart) const
619     {
620         return m_kart_status[kart].m_ident;
621     }   // getKartIdent
622     // ----------------------------------------------------------------------------------------
getKartScore(int krt) const623     int getKartScore(int krt) const { return m_kart_status[krt].m_score; }
624     // ----------------------------------------------------------------------------------------
getKartPrevScore(int krt) const625     int getKartPrevScore(int krt) const
626     {
627         return m_kart_status[krt].m_last_score;
628     }   // getKartPrevScore
629     // ----------------------------------------------------------------------------------------
getKartLocalPlayerId(int k) const630     int getKartLocalPlayerId(int k) const
631     {
632         return m_kart_status[k].m_local_player_id;
633     }   // getKartLocalPlayerId
634     // ----------------------------------------------------------------------------------------
getKartGlobalPlayerId(int k) const635     int getKartGlobalPlayerId(int k) const
636     {
637         return m_kart_status[k].m_global_player_id;
638     }   // getKartGlobalPlayerId
639     // ----------------------------------------------------------------------------------------
getOverallTime(int kart) const640     float getOverallTime(int kart) const
641     {
642         return m_kart_status[kart].m_overall_time;
643     }   // getOverallTime
644     // ----------------------------------------------------------------------------------------
getKartRaceTime(int kart) const645     float getKartRaceTime(int kart) const
646     {
647         return m_kart_status[kart].m_last_time;
648     }   // getKartRaceTime
649     // ----------------------------------------------------------------------------------------
getKartType(int kart) const650     KartType getKartType(int kart) const
651     {
652         return m_kart_status[kart].m_kart_type;
653     }   // getKartType
654     // ----------------------------------------------------------------------------------------
getPlayerHandicap(int kart) const655     HandicapLevel getPlayerHandicap(int kart) const
656     {
657         return m_kart_status[kart].m_handicap;
658     }   // getPlayerHandicap
659     // ----------------------------------------------------------------------------------------
hasBoostedAI(int kart) const660     bool hasBoostedAI(int kart) const
661     {
662         return m_kart_status[kart].m_boosted_ai;
663     }   // getKartRaceTime
664     // ----------------------------------------------------------------------------------------
setKartColor(int kart,float color)665     void setKartColor(int kart, float color)
666     {
667         m_kart_status[kart].m_color = color;
668     }   // setKartColor
669     // ----------------------------------------------------------------------------------------
getKartColor(int kart) const670     float getKartColor(int kart) const
671     {
672         return m_kart_status[kart].m_color;
673     }   // getKartColor
674     // ----------------------------------------------------------------------------------------
getCoinTarget() const675     int getCoinTarget() const { return m_coin_target; }
676     // ----------------------------------------------------------------------------------------
getTimeTarget() const677     float getTimeTarget() const { return m_time_target; }
678     // ----------------------------------------------------------------------------------------
getTrackNumber() const679     int getTrackNumber() const { return m_track_number; }
680     // ----------------------------------------------------------------------------------------
getNumOfTracks() const681     int getNumOfTracks() const { return (int)m_tracks.size(); }
682     // ----------------------------------------------------------------------------------------
683     /** Returns the list of AI karts to use. Used for networking, and for
684     *  the --ai= command line option. */
getAIKartList() const685     const std::vector<std::string>& getAIKartList() const
686     {
687         return m_ai_kart_list;
688     }   // getAIKartList
689     // ----------------------------------------------------------------------------------------
690     /** \brief get information about current mode (returns true if 'mode' is of
691     *  linear races type) */
isLinearRaceMode() const692     bool isLinearRaceMode() const
693     {
694         const int id = (int)m_minor_mode;
695         // info is stored in its ID for conveniance, see the macros LINEAR_RACE
696         // and BATTLE_ARENA above for exact meaning.
697         if(id > 999 && id < 2000) return true;
698         else return false;
699     }   // isLinearRaceMode
700 
701     // ----------------------------------------------------------------------------------------
702     /** \brief get information about given mode (returns true if 'mode' is of
703     *  linear races type) */
isLinearRaceMode(const MinorRaceModeType mode) const704     bool isLinearRaceMode(const MinorRaceModeType mode) const
705     {
706         const int id = (int)mode;
707         // info is stored in its ID for conveniance, see the macros LINEAR_RACE
708         // and BATTLE_ARENA above for exact meaning.
709         if(id > 999 && id < 2000) return true;
710         else return false;
711     }   // isLinearRaceMode
712 
713     // ----------------------------------------------------------------------------------------
714     /** \brief Returns true if the current mode is a battle mode. */
isBattleMode() const715     bool isBattleMode() const
716     {
717         const int id = (int)m_minor_mode;
718         // This uses the  numerical id of the mode, see the macros
719         // LINEAR_RACE and BATTLE_ARENA above for exact meaning.
720         if (id >= 2000 && id <= 2002) return true;
721         else            return false;
722     }   // isBattleMode
723 
724     // ----------------------------------------------------------------------------------------
725     /** \brief Returns true if the current mode is a soccer mode. */
isSoccerMode() const726     bool isSoccerMode() const
727     {
728         const int id = (int)m_minor_mode;
729         // This uses the  numerical id of the mode, see the macros
730         // LINEAR_RACE and BATTLE_ARENA above for exact meaning.
731         if (id == 2003) return true;
732         else            return false;
733     }   // isSoccerMode
734 
735     // ----------------------------------------------------------------------------------------
isTutorialMode() const736     bool isTutorialMode() const  { return m_minor_mode == MINOR_MODE_TUTORIAL; }
737 
738     // ----------------------------------------------------------------------------------------
isFollowMode() const739     bool isFollowMode() const    { return m_minor_mode == MINOR_MODE_FOLLOW_LEADER; }
740 
741     // ----------------------------------------------------------------------------------------
isCTFMode() const742     bool isCTFMode() const       { return m_minor_mode == MINOR_MODE_CAPTURE_THE_FLAG; }
743 
744     // ----------------------------------------------------------------------------------------
isEggHuntMode() const745     bool isEggHuntMode() const   { return m_minor_mode == MINOR_MODE_EASTER_EGG; }
746 
747     // ----------------------------------------------------------------------------------------
isTimeTrialMode() const748     bool isTimeTrialMode() const { return m_minor_mode == MINOR_MODE_TIME_TRIAL; }
749     // ----------------------------------------------------------------------------------------
750      /** \brief Returns the number of second's decimals to display */
currentModeTimePrecision() const751     int currentModeTimePrecision() const
752     {
753         return 3; // display milliseconds
754     }   // currentModeTimePrecision
755     // ----------------------------------------------------------------------------------------
756     /** \brief Returns true if the current mode has laps. */
modeHasLaps() const757     bool modeHasLaps() const
758     {
759         if (!isLinearRaceMode()) return false;
760         const int id = (int)m_minor_mode;
761         // See meaning of IDs above
762         const int answer = (id-1000)/100;
763         return answer!=0;
764     }   // modeHasLaps
765     // ----------------------------------------------------------------------------------------
766     /** Returns true if the currently selected minor mode has highscores. */
modeHasHighscores()767     bool modeHasHighscores()
768     {
769         //FIXME: this information is duplicated. RaceManager knows about it,
770         //       and each World may set m_use_highscores to true or false.
771         //       The reason for this duplication is that we might want to know
772         //       whether to display highscores without creating a World.
773         return !isBattleMode() &&
774                !isSoccerMode() &&
775                m_minor_mode != MINOR_MODE_FOLLOW_LEADER;
776     }   // modeHasHighscore
777     // ----------------------------------------------------------------------------------------
raceWasStartedFromOverworld() const778     bool raceWasStartedFromOverworld() const
779     {
780         return m_started_from_overworld;
781     }   // raceWasStartedFromOverworld
782 
783     // ----------------------------------------------------------------------------------------
784     /** \name Callbacks from the race classes
785      * These methods are to be used by the classes that manage the various
786      *  races, to let the race manager know about current status
787      */
allPlayerFinished() const788     bool allPlayerFinished() const
789     {
790         return m_num_finished_players == m_player_karts.size();
791     }   // allPlayerFinished
792     // ----------------------------------------------------------------------------------------
793     /** Sets the AI to use. This is used in networking mode to set the karts
794      *  that will be used by the server to the client. It will take precedence
795      *  over the random selection. */
setAIKartList(const std::vector<std::string> & rkl)796     void setAIKartList(const std::vector<std::string>& rkl)
797     {
798         m_ai_kart_list = rkl;
799     }   // setAIKartList
800     // ----------------------------------------------------------------------------------------
haveKartLastPositionOnOverworld()801     bool haveKartLastPositionOnOverworld()
802     {
803         return m_have_kart_last_position_on_overworld;
804     }   // haveKartLastPositionOnOverworld
805     // ----------------------------------------------------------------------------------------
setKartLastPositionOnOverworld(const Vec3 & pos)806     void setKartLastPositionOnOverworld(const Vec3 &pos)
807     {
808         m_have_kart_last_position_on_overworld = true;
809         m_kart_last_position_on_overworld = pos;
810     }   // setKartLastPositionOnOverworld
811     // ----------------------------------------------------------------------------------------
clearKartLastPositionOnOverworld()812     void clearKartLastPositionOnOverworld()
813     {
814         m_have_kart_last_position_on_overworld = false;
815     }   // clearKartLastPositionOnOverworld
816     // ----------------------------------------------------------------------------------------
getKartLastPositionOnOverworld()817     Vec3 getKartLastPositionOnOverworld()
818     {
819         return m_kart_last_position_on_overworld;
820     }   // getKartLastPositionOnOverworld
821     // ----------------------------------------------------------------------------------------
setRecordRace(bool record)822     void setRecordRace(bool record)
823     {
824         m_is_recording_race = record;
825     }   // setRecordRace
826     // ----------------------------------------------------------------------------------------
setRaceGhostKarts(bool ghost)827     void setRaceGhostKarts(bool ghost)
828     {
829         m_has_ghost_karts = ghost;
830     }   // setRaceGhostKarts
831     // ----------------------------------------------------------------------------------------
setWatchingReplay(bool watch)832     void setWatchingReplay(bool watch)
833     {
834         m_watching_replay = watch;
835     }   // setWatchingReplay
836     // ----------------------------------------------------------------------------------------
isRecordingRace() const837     bool isRecordingRace() const
838     {
839         return m_is_recording_race;
840     }   // isRecordingRace
841     // ----------------------------------------------------------------------------------------
hasGhostKarts() const842     bool hasGhostKarts() const
843     {
844         return m_has_ghost_karts;
845     }   // hasGhostKarts
846     // ----------------------------------------------------------------------------------------
isWatchingReplay() const847     bool isWatchingReplay() const
848     {
849         return m_watching_replay;
850     }   // isWatchingReplay
851     // ----------------------------------------------------------------------------------------
addSpareTireKart(const std::string & name)852     void addSpareTireKart(const std::string& name)
853     {
854         m_kart_status.push_back(KartStatus(name, 0, -1, -1,
855             -1, KT_SPARE_TIRE, HANDICAP_NONE));
856         m_num_spare_tire_karts++;
857         m_num_karts++;
858     }   // addSpareTireKart
859     // ----------------------------------------------------------------------------------------
setSpareTireKartNum(unsigned int i)860     void setSpareTireKartNum(unsigned int i)
861     {
862         m_num_spare_tire_karts = i;
863     }   // setSpareTireKartNum
864     // ----------------------------------------------------------------------------------------
getNumSpareTireKarts() const865     unsigned int getNumSpareTireKarts() const
866     {
867         return m_num_spare_tire_karts;
868     }   // getNumSpareTireKarts
869     // ----------------------------------------------------------------------------------------
870     void configGrandPrixResultFromNetwork(NetworkString& ns);
871     // ----------------------------------------------------------------------------------------
872     void clearNetworkGrandPrixResult();
873     // ----------------------------------------------------------------------------------------
setHitCaptureTime(int hc,float time)874     void setHitCaptureTime(int hc, float time)
875     {
876         m_hit_capture_limit = hc;
877         m_time_target = time;
878     }
879     // ----------------------------------------------------------------------------------------
getHitCaptureLimit() const880     int getHitCaptureLimit() const              { return m_hit_capture_limit; }
881     // ----------------------------------------------------------------------------------------
teamEnabled() const882     bool teamEnabled() const
883     {
884         return m_minor_mode == MINOR_MODE_SOCCER ||
885             m_minor_mode == MINOR_MODE_CAPTURE_THE_FLAG;
886     }
887     // ----------------------------------------------------------------------------------------
setFlagReturnTicks(unsigned ticks)888     void setFlagReturnTicks(unsigned ticks)    { m_flag_return_ticks = ticks; }
889     // ----------------------------------------------------------------------------------------
getFlagReturnTicks() const890     unsigned getFlagReturnTicks() const         { return m_flag_return_ticks; }
891     // ----------------------------------------------------------------------------------------
setFlagDeactivatedTicks(unsigned ticks)892     void setFlagDeactivatedTicks(unsigned ticks)
893                                           { m_flag_deactivated_ticks = ticks; }
894     // ----------------------------------------------------------------------------------------
getFlagDeactivatedTicks() const895     unsigned getFlagDeactivatedTicks() const
896                                            { return m_flag_deactivated_ticks; }
897     // ----------------------------------------------------------------------------------------
898     /** Whether the current game mode allow live joining even the current game
899      *. started in network*/
supportsLiveJoining() const900     bool supportsLiveJoining() const
901     {
902         return m_minor_mode == MINOR_MODE_SOCCER ||
903             m_minor_mode == MINOR_MODE_CAPTURE_THE_FLAG ||
904             m_minor_mode == MINOR_MODE_FREE_FOR_ALL;
905     }
906 };   // RaceManager
907 
908 #endif
909 
910 /* EOF */
911