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 #include "race/race_manager.hpp"
20 
21 #include <iostream>
22 #include <algorithm>
23 
24 #include "challenges/unlock_manager.hpp"
25 #include "config/player_manager.hpp"
26 #include "config/saved_grand_prix.hpp"
27 #include "config/stk_config.hpp"
28 #include "config/user_config.hpp"
29 #include "graphics/irr_driver.hpp"
30 #include "guiengine/message_queue.hpp"
31 #include "input/device_manager.hpp"
32 #include "input/input_manager.hpp"
33 #include "karts/abstract_kart.hpp"
34 #include "karts/controller/controller.hpp"
35 #include "karts/kart_properties_manager.hpp"
36 #include "main_loop.hpp"
37 #include "modes/capture_the_flag.hpp"
38 #include "modes/cutscene_world.hpp"
39 #include "modes/demo_world.hpp"
40 #include "modes/easter_egg_hunt.hpp"
41 #include "modes/follow_the_leader.hpp"
42 #include "modes/free_for_all.hpp"
43 #include "modes/overworld.hpp"
44 #include "modes/standard_race.hpp"
45 #include "modes/tutorial_world.hpp"
46 #include "modes/world.hpp"
47 #include "modes/three_strikes_battle.hpp"
48 #include "modes/soccer_world.hpp"
49 #include "network/protocol_manager.hpp"
50 #include "network/network_config.hpp"
51 #include "network/network_string.hpp"
52 #include "replay/replay_play.hpp"
53 #include "scriptengine/property_animator.hpp"
54 #include "states_screens/grand_prix_cutscene.hpp"
55 #include "states_screens/grand_prix_lose.hpp"
56 #include "states_screens/grand_prix_win.hpp"
57 #include "states_screens/kart_selection.hpp"
58 #include "states_screens/main_menu_screen.hpp"
59 #include "states_screens/state_manager.hpp"
60 #include "tracks/track_manager.hpp"
61 #include "utils/ptr_vector.hpp"
62 #include "utils/stk_process.hpp"
63 #include "utils/string_utils.hpp"
64 #include "utils/translation.hpp"
65 
66 //=============================================================================================
67 RaceManager* g_race_manager[PT_COUNT];
68 //---------------------------------------------------------------------------------------------
get()69 RaceManager* RaceManager::get()
70 {
71     ProcessType type = STKProcess::getType();
72     return g_race_manager[type];
73 }   // get
74 
75 //---------------------------------------------------------------------------------------------
create()76 void RaceManager::create()
77 {
78     ProcessType type = STKProcess::getType();
79     g_race_manager[type] = new RaceManager();
80 }   // create
81 
82 //---------------------------------------------------------------------------------------------
destroy()83 void RaceManager::destroy()
84 {
85     ProcessType type = STKProcess::getType();
86     delete g_race_manager[type];
87     g_race_manager[type] = NULL;
88 }   // destroy
89 
90 //---------------------------------------------------------------------------------------------
clear()91 void RaceManager::clear()
92 {
93     memset(g_race_manager, 0, sizeof(g_race_manager));
94 }   // clear
95 
96 //---------------------------------------------------------------------------------------------
97 /** Constructs the race manager.
98  */
RaceManager()99 RaceManager::RaceManager()
100 {
101     // Several code depends on this, e.g. kart_properties
102     assert(DIFFICULTY_FIRST == 0);
103     m_num_karts          = UserConfigParams::m_default_num_karts;
104     m_num_ghost_karts    = 0;
105     m_difficulty         = DIFFICULTY_HARD;
106     m_major_mode         = MAJOR_MODE_SINGLE;
107     m_minor_mode         = MINOR_MODE_NORMAL_RACE;
108     m_ai_superpower      = SUPERPOWER_NONE;
109     m_track_number       = 0;
110     m_coin_target        = 0;
111     m_started_from_overworld = false;
112     m_have_kart_last_position_on_overworld = false;
113     m_num_local_players = 0;
114     m_hit_capture_limit = 0;
115     m_flag_return_ticks = stk_config->time2Ticks(20.0f);
116     m_flag_deactivated_ticks = stk_config->time2Ticks(3.0f);
117     setMaxGoal(0);
118     setTimeTarget(0.0f);
119     setReverseTrack(false);
120     setRecordRace(false);
121     setRaceGhostKarts(false);
122     setWatchingReplay(false);
123     setTrack("jungle");
124     m_default_ai_list.clear();
125     setNumPlayers(0);
126     setSpareTireKartNum(0);
127 }   // RaceManager
128 
129 //---------------------------------------------------------------------------------------------
130 /** Destructor for the race manager.
131  */
~RaceManager()132 RaceManager::~RaceManager()
133 {
134 }   // ~RaceManager
135 
136 //---------------------------------------------------------------------------------------------
137 /** Resets the race manager in preparation for a new race. It sets the
138  *  counter of finished karts to zero. It is called by world when
139  *  restarting a race.
140  */
reset()141 void RaceManager::reset()
142 {
143     m_num_finished_karts   = 0;
144     m_num_finished_players = 0;
145 }  // reset
146 
147 // ----------------------------------------------------------------------------
148 /** Sets the default list of AI karts to use.
149  *  \param ai_kart_list List of the identifier of the karts to use.
150  */
setDefaultAIKartList(const std::vector<std::string> & ai_list)151 void RaceManager::setDefaultAIKartList(const std::vector<std::string>& ai_list)
152 {
153     for(unsigned int i=0; i<ai_list.size(); i++)
154     {
155         const std::string &name=ai_list[i];
156         const KartProperties *kp = kart_properties_manager->getKart(name);
157         if(!kp)
158         {
159             Log::warn("RaceManager", "Kart '%s' is unknown and therefore ignored.",
160                       name.c_str());
161             continue;
162         }
163         // This doesn't work anymore, since this is called when
164         // handling the command line options, at which time the
165         // player (and therefore the current slot) is not defined yet.
166         //if(unlock_manager->getCurrentSlot()->isLocked(name))
167         //{
168         //   Log::info("RaceManager", "Kart '%s' is locked and therefore ignored.",
169         //           name.c_str());
170         //    continue;
171         //}
172         m_default_ai_list.push_back(name);
173     }
174 }   // setDefaultAIKartList
175 
176 //---------------------------------------------------------------------------------------------
177 /** \brief Sets a player kart (local and non-local).
178  *  \param player_id  Id of the player.
179  *  \param ki         Kart info structure for this player.
180  */
setPlayerKart(unsigned int player_id,const RemoteKartInfo & ki)181 void RaceManager::setPlayerKart(unsigned int player_id, const RemoteKartInfo& ki)
182 {
183     m_player_karts[player_id] = ki;
184 }   // setPlayerKart
185 
186 // ----------------------------------------------------------------------------
setPlayerKart(unsigned int player_id,const std::string & kart_name)187 void RaceManager::setPlayerKart(unsigned int player_id,
188                                  const std::string &kart_name)
189 {
190     const PlayerProfile* profile =
191                     StateManager::get()->getActivePlayerProfile(player_id);
192     RemoteKartInfo rki(player_id, kart_name, profile->getName(), 0, false);
193     m_player_karts[player_id] = rki;
194 }   // setPlayerKart
195 
196 //---------------------------------------------------------------------------------------------
197 /** Sets additional information for a player to indicate which soccer team it
198  *  belongs to.
199 */
setKartTeam(unsigned int player_id,KartTeam team)200 void RaceManager::setKartTeam(unsigned int player_id, KartTeam team)
201 {
202     assert(player_id < m_player_karts.size());
203 
204     m_player_karts[player_id].setKartTeam(team);
205 }   // setKartTeam
206 
207 //---------------------------------------------------------------------------------------------
208 /** Sets the handicap for a player.
209  */
setPlayerHandicap(unsigned int player_id,HandicapLevel handicap)210 void RaceManager::setPlayerHandicap(unsigned int player_id, HandicapLevel handicap)
211 {
212     assert(player_id < m_player_karts.size());
213 
214     m_player_karts[player_id].setHandicap(handicap);
215 }   // setPlayerHandicap
216 
217 //---------------------------------------------------------------------------------------------
218 /** Returns a pointer to the kart which has a given GP rank.
219  *  \param n The rank (1 to number of karts) to look for.
220  */
getKartWithGPRank(unsigned int n)221 const AbstractKart *RaceManager::getKartWithGPRank(unsigned int n)
222 {
223     for(unsigned int i=0; i<m_kart_status.size(); i++)
224         if(m_kart_status[i].m_gp_rank == (int)n)
225             return World::getWorld()->getKart(i);
226     return NULL;
227 }   // getKLartWithGPRank
228 
229 //---------------------------------------------------------------------------------------------
230 /** Returns the GP rank (between 1 and number of karts) of a local player.
231  *  \param player_id Local id of the player.
232  */
getLocalPlayerGPRank(const int player_id) const233 int RaceManager::getLocalPlayerGPRank(const int player_id) const
234 {
235     const int amount = (int)m_kart_status.size();
236     for (int n=0; n<amount; n++)
237     {
238         if (m_kart_status[n].m_local_player_id == player_id)
239         {
240             return m_kart_status[n].m_gp_rank;
241         }
242     }
243     return -1;
244 }   // getLocalPlayerGPRank
245 
246 //---------------------------------------------------------------------------------------------
247 /** Sets the number of players and optional the number of local players.
248  *  \param num Number of players.
249  *  \param local_players Number of local players, only used from networking.
250  */
setNumPlayers(int players,int local_players)251 void RaceManager::setNumPlayers(int players, int local_players)
252 {
253     // Clear all previous game info from network (like country code atm)
254     // The rest info need to be store for overworld, see #3980
255     for (RemoteKartInfo& rki : m_player_karts)
256         rki.setCountryCode("");
257     m_player_karts.resize(players);
258     if(local_players>-1)
259         m_num_local_players = local_players;
260     else
261         m_num_local_players = players;
262 }   // setNumPlayers
263 
264 // ----------------------------------------------------------------------------
265 /** Converst the difficulty given as a string into a Difficult enum. Defaults
266  *  to HARD.
267  *  \param difficulty The difficulty as string.
268  */
269 RaceManager::Difficulty
convertDifficulty(const std::string & difficulty)270                   RaceManager::convertDifficulty(const std::string &difficulty)
271 {
272     if (difficulty == "novice")
273         return DIFFICULTY_EASY;
274     else if (difficulty == "intermediate")
275         return DIFFICULTY_MEDIUM;
276     else if (difficulty == "expert")
277         return DIFFICULTY_HARD;
278     else if (difficulty == "best")
279         return DIFFICULTY_BEST;
280     else
281         return DIFFICULTY_HARD;
282 }   // convertDifficulty
283 
284 //---------------------------------------------------------------------------------------------
285 /** Sets the difficulty to use.
286  *  \param diff The difficulty to use.
287  */
setDifficulty(Difficulty diff)288 void RaceManager::setDifficulty(Difficulty diff)
289 {
290     m_difficulty = diff;
291 }   // setDifficulty
292 
293 //---------------------------------------------------------------------------------------------
294 /** Sets a single track to be used in the next race.
295  *  \param track The identifier of the track to use.
296  */
setTrack(const std::string & track)297 void RaceManager::setTrack(const std::string& track)
298 {
299     m_tracks.clear();
300     m_tracks.push_back(track);
301 
302     m_coin_target = 0;
303 }   // setTrack
304 
305 //---------------------------------------------------------------------------------------------
306 /** \brief Computes the list of random karts to be used for the AI.
307  *  If a command line option specifies karts, they will be used first
308  */
computeRandomKartList()309 void RaceManager::computeRandomKartList()
310 {
311     int n = m_num_karts - (int)m_player_karts.size();
312     if(UserConfigParams::logMisc())
313         Log::info("RaceManager", "AI karts count = %d for m_num_karts = %d and "
314             "m_player_karts.size() = %d", n, m_num_karts, m_player_karts.size());
315 
316     // If less kart selected than there are player karts, adjust the number of
317     // karts to the minimum
318     if(n<0)
319     {
320         m_num_karts -= n;
321         n = 0;
322     }
323 
324     m_ai_kart_list.clear();
325 
326     //Use the command line options AI list.
327     unsigned int m = std::min( (unsigned) m_num_karts,  (unsigned)m_default_ai_list.size());
328 
329     for(unsigned int i=0; i<m; i++)
330     {
331         m_ai_kart_list.push_back(m_default_ai_list[i]);
332         n--;
333     }
334 
335     if(n>0)
336         kart_properties_manager->getRandomKartList(n, &m_player_karts,
337                                                    &m_ai_kart_list   );
338 
339     if (m_ai_kart_override != "")
340     {
341         for (unsigned int n = 0; n < m_ai_kart_list.size(); n++)
342         {
343             m_ai_kart_list[n] = m_ai_kart_override;
344         }
345     }
346 
347 }   // computeRandomKartList
348 
349 //---------------------------------------------------------------------------------------------
350 /** \brief Starts a new race or GP (or other mode).
351  *  It sets up the list of player karts, AI karts, GP tracks if relevant
352  *  etc.
353  *  \pre The list of AI karts to use must be set up first. This is
354  *       usually being done by a call to computeRandomKartList() from
355  *       NetworkManager::setupPlayerKartInfo, but could be done differently
356  *       (e.g. depending on user command line options to test certain AIs)
357  *  \param from_overworld True if the race/GP is started from overworld
358  *         (used to return to overworld at end of race/GP).
359  */
startNew(bool from_overworld)360 void RaceManager::startNew(bool from_overworld)
361 {
362     m_num_ghost_karts = 0;
363     if (m_has_ghost_karts)
364         m_num_ghost_karts = ReplayPlay::get()->getNumGhostKart();
365 
366     m_started_from_overworld = from_overworld;
367     if (m_started_from_overworld) m_continue_saved_gp = false;
368     m_saved_gp = NULL; // There will be checks for this being NULL done later
369 
370     if (m_major_mode==MAJOR_MODE_GRAND_PRIX)
371     {
372         // GP: get tracks, laps and reverse info from grand prix
373         m_tracks        = m_grand_prix.getTrackNames();
374         m_num_laps      = m_grand_prix.getLaps();
375         m_reverse_track = m_grand_prix.getReverse();
376 
377         if (!NetworkConfig::get()->isNetworking())
378         {
379             // We look if Player 1 has a saved version of this GP.
380             m_saved_gp = SavedGrandPrix::getSavedGP(
381                                          StateManager::get()
382                                          ->getActivePlayerProfile(0)
383                                          ->getUniqueID(),
384                                          m_grand_prix.getId(),
385                                          m_minor_mode,
386                                          (unsigned int)m_player_karts.size());
387 
388             // Saved GP only in offline mode
389             if (m_continue_saved_gp)
390             {
391                 if (m_saved_gp == NULL)
392                 {
393                     Log::error("Race Manager", "Can not continue Grand Prix '%s'"
394                                                "because it could not be loaded",
395                                                m_grand_prix.getId().c_str());
396                     m_continue_saved_gp = false; // simple and working
397                 }
398                 else
399                 {
400                     setNumKarts(m_saved_gp->getTotalKarts());
401                     setupPlayerKartInfo();
402                     m_grand_prix.changeReverse((GrandPrixData::GPReverseType)
403                                                 m_saved_gp->getReverseType());
404                     m_reverse_track = m_grand_prix.getReverse();
405                 }   // if m_saved_gp==NULL
406             }   // if m_continue_saved_gp
407         }   // if !network_world
408     }   // if grand prix
409 
410     // command line parameters: negative numbers=all karts
411     if(m_num_karts < 0 ) m_num_karts = stk_config->m_max_karts;
412     if((size_t)m_num_karts < m_player_karts.size())
413         m_num_karts = (int)m_player_karts.size();
414 
415     // Create the kart status data structure to keep track of scores, times, ...
416     // ==========================================================================
417     m_kart_status.clear();
418     if (m_num_ghost_karts > 0)
419         m_num_karts += m_num_ghost_karts;
420 
421     Log::verbose("RaceManager", "Nb of karts=%u, ghost karts:%u ai:%lu players:%lu\n",
422         (unsigned int) m_num_karts, m_num_ghost_karts, m_ai_kart_list.size(), m_player_karts.size());
423 
424     assert((unsigned int)m_num_karts == m_num_ghost_karts+m_ai_kart_list.size()+m_player_karts.size());
425 
426     // First add the ghost karts (if any)
427     // ----------------------------------------
428     // GP ranks start with -1 for the leader.
429     int init_gp_rank = getMinorMode()==MINOR_MODE_FOLLOW_LEADER ? -1 : 0;
430     if (m_num_ghost_karts > 0)
431     {
432         for(unsigned int i = 0; i < m_num_ghost_karts; i++)
433         {
434             m_kart_status.push_back(KartStatus(ReplayPlay::get()->getGhostKartName(i),
435                 i, -1, -1, init_gp_rank, KT_GHOST, HANDICAP_NONE));
436             init_gp_rank ++;
437         }
438     }
439 
440     // Then add the AI karts (randomly chosen)
441     // ----------------------------------------
442     const unsigned int ai_kart_count = (unsigned int)m_ai_kart_list.size();
443     for(unsigned int i = 0; i < ai_kart_count; i++)
444     {
445         m_kart_status.push_back(KartStatus(m_ai_kart_list[i], i, -1, -1,
446             init_gp_rank, KT_AI, HANDICAP_NONE));
447         init_gp_rank ++;
448         if(UserConfigParams::m_ftl_debug)
449         {
450             Log::debug("RaceManager", "[ftl] rank %d ai-kart %s", init_gp_rank,
451                    m_ai_kart_list[i].c_str());
452         }
453     }
454 
455     // Finally add the players, which start behind the AI karts
456     // -----------------------------------------------------
457     for(unsigned int i = 0; i < m_player_karts.size(); i++)
458     {
459         KartType kt= m_player_karts[i].isNetworkPlayer() ? KT_NETWORK_PLAYER
460                                                          : KT_PLAYER;
461         m_kart_status.push_back(KartStatus(m_player_karts[i].getKartName(), i,
462                                            m_player_karts[i].getLocalPlayerId(),
463                                            m_player_karts[i].getGlobalPlayerId(),
464                                            init_gp_rank, kt,
465                                            m_player_karts[i].getHandicap()));
466         if(UserConfigParams::m_ftl_debug)
467         {
468             Log::debug("RaceManager", "[ftl] rank %d kart %s", init_gp_rank,
469                 m_player_karts[i].getKartName().c_str());
470         }
471         init_gp_rank ++;
472     }
473 
474     m_track_number = 0;
475     if (m_major_mode == MAJOR_MODE_GRAND_PRIX)
476     {
477         if (m_continue_saved_gp)
478         {
479             int next_track = m_saved_gp->getNextTrack();
480             if (next_track < (int)m_tracks.size())
481                 m_track_number = next_track;
482             m_saved_gp->loadKarts(m_kart_status);
483         }
484         else
485         {
486             while (m_saved_gp != NULL)
487             {
488                 m_saved_gp->remove();
489                 m_saved_gp = SavedGrandPrix::getSavedGP(
490                                              StateManager::get()
491                                              ->getActivePlayerProfile(0)
492                                              ->getUniqueID(),
493                                              m_grand_prix.getId(),
494                                              m_minor_mode,
495                                              (unsigned int)m_player_karts.size());
496             }   // while m_saved_gp
497         }   // if m_continue_saved_gp
498     }   // if grand prix
499 
500     startNextRace();
501 }   // startNew
502 
503 //---------------------------------------------------------------------------------------------
504 /** \brief Starts the next (or first) race.
505  *  It sorts the kart status data structure
506  *  according to the number of points, and then creates the world().
507  */
startNextRace()508 void RaceManager::startNextRace()
509 {
510     ProcessType type = STKProcess::getType();
511     main_loop->renderGUI(0);
512     // Uncomment to debug audio leaks
513     // sfx_manager->dump();
514 
515     if (type == PT_MAIN)
516     {
517         IrrlichtDevice* device = irr_driver->getDevice();
518         GUIEngine::clearLoadingTips();
519         GUIEngine::renderLoading(true/*clearIcons*/, false/*launching*/, false/*update_tips*/);
520         device->getVideoDriver()->endScene();
521         device->getVideoDriver()->beginScene(true, true,
522                                             video::SColor(255,100,101,140));
523     }
524 
525     m_num_finished_karts   = 0;
526     m_num_finished_players = 0;
527 
528     // if subsequent race, sort kart status structure
529     // ==============================================
530     if (m_track_number > 0)
531     {
532         // In follow the leader mode do not change the first kart,
533         // since it's always the leader.
534         int offset = (m_minor_mode==MINOR_MODE_FOLLOW_LEADER) ? 1 : 0;
535 
536         // Keep players at the end if needed
537         int player_last_offset = 0;
538         if (UserConfigParams::m_gp_player_last)
539         {
540             // Doing this is enough to keep player karts at
541             // the end because of the simple reason that they
542             // are at the end when getting added. Keep them out
543             // of the later sorting and they will stay there.
544             player_last_offset = (int)m_player_karts.size();
545         }
546 
547         std::sort(m_kart_status.begin()+offset,
548                   m_kart_status.end() - player_last_offset);
549         // reverse kart order if flagged in user's config
550         if (UserConfigParams::m_gp_most_points_first)
551         {
552             std::reverse(m_kart_status.begin()+offset,
553                          m_kart_status.end() - player_last_offset);
554         }
555     }   // not first race
556 
557     // set boosted AI status for AI karts
558     int boosted_ai_count = std::min<int>((int)m_ai_kart_list.size(),
559                                          ((int)(m_kart_status.size())-2)/4 + 1);
560     if (boosted_ai_count > 4) boosted_ai_count = 4;
561     int ai_count = (int)m_ai_kart_list.size();
562 
563     for (unsigned int i=0;i<m_kart_status.size();i++)
564     {
565         if (m_kart_status[i].m_kart_type == KT_AI)
566         {
567             if (boosted_ai_count > 0 &&
568                 (UserConfigParams::m_gp_most_points_first ||
569                 ai_count == boosted_ai_count))
570             {
571                 m_kart_status[i].m_boosted_ai = true;
572                 boosted_ai_count--;
573             }
574             else
575             {
576                 m_kart_status[i].m_boosted_ai = false;
577             }
578             ai_count--;
579         }
580     }
581 
582     main_loop->renderGUI(100);
583 
584     // the constructor assigns this object to the global
585     // variable world. Admittedly a bit ugly, but simplifies
586     // handling of objects which get created in the constructor
587     // and need world to be defined.
588     if(DemoWorld::isDemoMode())
589         World::setWorld(new DemoWorld());
590     else if(ProfileWorld::isProfileMode())
591         World::setWorld(new ProfileWorld());
592     else if(m_minor_mode==MINOR_MODE_FOLLOW_LEADER)
593         World::setWorld(new FollowTheLeaderRace());
594     else if(m_minor_mode==MINOR_MODE_NORMAL_RACE ||
595             m_minor_mode==MINOR_MODE_TIME_TRIAL)
596         World::setWorld(new StandardRace());
597     else if(m_minor_mode==MINOR_MODE_TUTORIAL)
598         World::setWorld(new TutorialWorld());
599     else if (isBattleMode())
600     {
601         if (m_minor_mode == MINOR_MODE_3_STRIKES)
602             World::setWorld(new ThreeStrikesBattle());
603         else if (m_minor_mode == MINOR_MODE_FREE_FOR_ALL)
604             World::setWorld(new FreeForAll());
605         else if (m_minor_mode == MINOR_MODE_CAPTURE_THE_FLAG)
606             World::setWorld(new CaptureTheFlag());
607     }
608     else if(m_minor_mode==MINOR_MODE_SOCCER)
609         World::setWorld(new SoccerWorld());
610     else if(m_minor_mode==MINOR_MODE_OVERWORLD)
611         World::setWorld(new OverWorld());
612     else if(m_minor_mode==MINOR_MODE_CUTSCENE)
613         World::setWorld(new CutsceneWorld());
614     else if(m_minor_mode==MINOR_MODE_EASTER_EGG)
615         World::setWorld(new EasterEggHunt());
616     else
617     {
618         Log::error("RaceManager", "Could not create given race mode.");
619         assert(0);
620     }
621     main_loop->renderGUI(200);
622 
623     // A second constructor phase is necessary in order to be able to
624     // call functions which are overwritten (otherwise polymorphism
625     // will fail and the results will be incorrect). Also in init() functions
626     // can be called that use World::getWorld().
627     World::getWorld()->init();
628     main_loop->renderGUI(8000);
629     // Now initialise all values that need to be reset from race to race
630     // Calling this here reduces code duplication in init and restartRace()
631     // functions.
632     World::getWorld()->reset();
633 
634     if (NetworkConfig::get()->isNetworking())
635     {
636         for (unsigned i = 0; i < getNumPlayers(); i++)
637         {
638             // Eliminate all reserved players in the begining
639             const RemoteKartInfo& rki = getKartInfo(i);
640             if (rki.isReserved())
641             {
642                 AbstractKart* k = World::getWorld()->getKart(i);
643                 World::getWorld()->eliminateKart(i,
644                     false/*notify_of_elimination*/);
645                 k->setPosition(
646                     World::getWorld()->getCurrentNumKarts() + 1);
647                 k->finishedRace(World::getWorld()->getTime(),
648                     true/*from_server*/);
649             }
650         }
651     }
652 
653     if (type == PT_MAIN)
654         irr_driver->onLoadWorld();
655     main_loop->renderGUI(8100);
656 
657     // Save the current score and set last time to zero. This is necessary
658     // if someone presses esc after finishing a gp, and selects restart:
659     // The race is rerun, and the points and scores get reset ... but if
660     // a kart hasn't finished the race at this stage, last_score and time
661     // would be undefined.
662     for(int i=0; i<m_num_karts; i++)
663     {
664         m_kart_status[i].m_last_score = m_kart_status[i].m_score;
665         m_kart_status[i].m_last_time  = 0;
666     }
667     main_loop->renderGUI(8200);
668 }   // startNextRace
669 
670 //---------------------------------------------------------------------------------------------
671 /** \brief Start the next race or go back to the start screen
672  * If there are more races to do, starts the next race, otherwise
673  * calls exitRace to finish the race.
674  */
next()675 void RaceManager::next()
676 {
677     if (STKProcess::getType() == PT_MAIN)
678         PropertyAnimator::get()->clear();
679     World::deleteWorld();
680     m_num_finished_karts   = 0;
681     m_num_finished_players = 0;
682     m_track_number++;
683     if(m_track_number<(int)m_tracks.size())
684     {
685         if (m_major_mode == MAJOR_MODE_GRAND_PRIX &&
686             !NetworkConfig::get()->isNetworking())
687         {
688             // Saving GP state
689             saveGP();
690         }
691         startNextRace();
692     }
693     else
694     {
695         exitRace();
696     }
697 }   // next
698 
699 //---------------------------------------------------------------------------------------------
700 /** Saves the current GP to the config.
701  */
saveGP()702 void RaceManager::saveGP()
703 {
704     // If Player 1 has already saved a GP, we adapt it
705     if (m_saved_gp != NULL)
706     {
707         m_saved_gp->setKarts(m_kart_status);
708         m_saved_gp->setNextTrack(m_track_number);
709     }
710     else  if(!m_grand_prix.isRandomGP())
711     {
712         m_saved_gp = new SavedGrandPrix(
713             StateManager::get()->getActivePlayerProfile(0)->getUniqueID(),
714             m_grand_prix.getId(),
715             m_minor_mode,
716             m_difficulty,
717             (int)m_player_karts.size(),
718             m_track_number,
719             m_grand_prix.getReverseType(),
720             m_kart_status);
721 
722         // If a new GP is saved, delete any other saved data for this
723         // GP at the same difficulty (even if #karts is different, otherwise
724         // the user has to remember the number of AI karts, with no indication
725         // on which ones are saved).
726         for (unsigned int i = 0;
727             i < UserConfigParams::m_saved_grand_prix_list.size();)
728         {
729             // Delete other save files (and random GP, which should never
730             // have been saved in the first place)
731             const SavedGrandPrix &sgp =
732                                   UserConfigParams::m_saved_grand_prix_list[i];
733             if (sgp.getGPID() == "random"                          ||
734                 (sgp.getGPID() == m_saved_gp->getGPID() &&
735                  sgp.getDifficulty() == m_saved_gp->getDifficulty())    )
736             {
737                 UserConfigParams::m_saved_grand_prix_list.erase(i);
738             }
739             else i++;
740         }
741         UserConfigParams::m_saved_grand_prix_list.push_back(m_saved_gp);
742     }
743 
744     user_config->saveConfig();
745 }   // saveGP
746 
747 //---------------------------------------------------------------------------------------------
748 
749 /** This class is only used in computeGPRanks, but the C++ standard
750  *  forbids the usage of local data type in templates, so we have to
751  *  declare it outside of the function. This class is used to store
752  *  and compare data for determining the GP rank.
753  */
754 namespace computeGPRanksData
755 {
756     class SortData
757     {
758     public:
759         int m_score;
760         int m_position;
761         float m_race_time;
operator <(const SortData & a)762         bool operator<(const SortData &a)
763         {
764             return ( (m_score > a.m_score) ||
765                 (m_score == a.m_score && m_race_time < a.m_race_time) );
766         }
767 
768     };   // SortData
769 }   // namespace
770 
771 // ----------------------------------------------------------------------------
772 /** Sort karts and update the m_gp_rank KartStatus member, in preparation
773  *  for future calls to RaceManager::getKartGPRank or
774  *  RaceManager::getKartWithGPRank
775  */
computeGPRanks()776 void RaceManager::computeGPRanks()
777 {
778     // calculate the rank of each kart
779     const unsigned int NUM_KARTS = getNumberOfKarts();
780     PtrVector<computeGPRanksData::SortData> sort_data;
781 
782     // Ignore the first kart if it's a follow-the-leader race.
783     int start=(getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER);
784     if (start)
785     {
786         // fill values for leader
787         computeGPRanksData::SortData *sd = new computeGPRanksData::SortData();
788 
789         sd->m_position  = -1;
790         sd->m_score     = -1;
791         sd->m_race_time = -1;
792         sort_data.push_back(sd);
793         m_kart_status[0].m_gp_rank = -1;
794         if(UserConfigParams::m_ftl_debug)
795         {
796             Log::debug("Race Manager","[ftl] kart '%s' has position %d.",
797                        World::getWorld()->getKart(0)->getIdent().c_str(),
798                        sd->m_position);
799         }
800     }
801     for (unsigned int kart_id = start; kart_id < NUM_KARTS; ++kart_id)
802     {
803         computeGPRanksData::SortData *sd = new computeGPRanksData::SortData();
804         sd->m_position  = kart_id;
805         sd->m_score     = getKartScore(kart_id);
806         sd->m_race_time = getOverallTime(kart_id);
807         sort_data.push_back(sd);
808         if(UserConfigParams::m_ftl_debug)
809         {
810             Log::debug("Race Manager",
811                        "[ftl] kart '%s' has position %d score %d.",
812                        World::getWorld()->getKart(kart_id)->getIdent().c_str(),
813                        sd->m_position, sd->m_score);
814         }
815     }
816 
817     sort_data.insertionSort(start);
818     for (unsigned int i=start; i < NUM_KARTS; ++i)
819     {
820         if(UserConfigParams::m_ftl_debug)
821         {
822             const AbstractKart *kart =
823                 World::getWorld()->getKart(sort_data[i].m_position);
824             Log::debug("Race Manager","[ftl] kart '%s' has now position %d.",
825                 kart->getIdent().c_str(),
826                 i-start);
827         }
828 
829         m_kart_status[sort_data[i].m_position].m_gp_rank = i - start;
830     }
831 }   // computeGPRanks
832 
833 //---------------------------------------------------------------------------------------------
834 /** \brief Exit a race (and don't start the next one)
835  * \note In GP, displays the GP result screen first
836  * \param delete_world If set deletes the world.
837  */
exitRace(bool delete_world)838 void RaceManager::exitRace(bool delete_world)
839 {
840     // Only display the grand prix result screen if all tracks
841     // were finished, and not when a race is aborted.
842     MessageQueue::discardStatic();
843     ProcessType type = STKProcess::getType();
844 
845     if ( m_major_mode==MAJOR_MODE_GRAND_PRIX &&
846          m_track_number==(int)m_tracks.size()   )
847     {
848         PlayerManager::getCurrentPlayer()->grandPrixFinished();
849         if (m_major_mode == MAJOR_MODE_GRAND_PRIX &&
850             !NetworkConfig::get()->isNetworking())
851         {
852             if(m_saved_gp != NULL)
853                 m_saved_gp->remove();
854         }
855         StateManager::get()->resetAndGoToScreen( MainMenuScreen::getInstance() );
856 
857         bool some_human_player_well_ranked = false;
858         bool some_human_player_won = false;
859         const unsigned int kart_status_count = (unsigned int)m_kart_status.size();
860 
861         const int loserThreshold = 3;
862 
863         std::pair<std::string, float> winners[3];
864         // because we don't care about AIs that lost
865         std::vector<std::pair<std::string, float> > humanLosers;
866         for (unsigned int i=0; i < kart_status_count; ++i)
867         {
868             if(UserConfigParams::logMisc())
869             {
870                 Log::info("RaceManager", "%s has GP final rank %d",
871                     m_kart_status[i].m_ident.c_str(), m_kart_status[i].m_gp_rank);
872             }
873 
874             const int rank = m_kart_status[i].m_gp_rank;
875             if (rank >= 0 && rank < loserThreshold)
876             {
877                 winners[rank].first = m_kart_status[i].m_ident;
878                 winners[rank].second = m_kart_status[i].m_color;
879                 if (m_kart_status[i].m_kart_type == KT_PLAYER ||
880                     m_kart_status[i].m_kart_type == KT_NETWORK_PLAYER)
881                 {
882                     some_human_player_well_ranked = true;
883                     if (rank == 0)
884                         some_human_player_won = true;
885                 }
886             }
887             else if (rank >= loserThreshold)
888             {
889                 if (m_kart_status[i].m_kart_type == KT_PLAYER ||
890                     m_kart_status[i].m_kart_type == KT_NETWORK_PLAYER)
891                 {
892                     humanLosers.emplace_back(m_kart_status[i].m_ident, m_kart_status[i].m_color);
893                 }
894             }
895         }
896 
897         if (delete_world)
898         {
899             if (type == PT_MAIN)
900                 PropertyAnimator::get()->clear();
901             World::deleteWorld();
902         }
903         delete_world = false;
904 
905         StateManager::get()->enterGameState();
906         setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
907         setNumKarts(0);
908         setNumPlayers(0);
909 
910         if (some_human_player_well_ranked)
911         {
912             startSingleRace("gpwin", 999,
913                                   raceWasStartedFromOverworld());
914             GrandPrixWin* scene = GrandPrixWin::getInstance();
915             scene->push();
916             scene->setKarts(winners);
917             scene->setPlayerWon(some_human_player_won);
918         }
919         else
920         {
921             startSingleRace("gplose", 999,
922                                   raceWasStartedFromOverworld());
923             GrandPrixLose* scene = GrandPrixLose::getInstance();
924             scene->push();
925 
926             if (humanLosers.size() >= 1)
927             {
928                 scene->setKarts(humanLosers);
929             }
930             else
931             {
932                 Log::error("RaceManager", "There are no winners and no losers."
933                            "This should have never happened\n");
934                 std::vector<std::pair<std::string, float> > karts;
935                 karts.emplace_back(UserConfigParams::m_default_kart, 0.0f);
936                 scene->setKarts(karts);
937             }
938         }
939     }
940 
941     if (delete_world)
942     {
943         if (type == PT_MAIN)
944             PropertyAnimator::get()->clear();
945         World::deleteWorld();
946     }
947 
948     m_saved_gp = NULL;
949     m_track_number = 0;
950 }   // exitRace
951 
952 //---------------------------------------------------------------------------------------------
953 /** A kart has finished the race at the specified time (which can be
954  *  different from World::getWorld()->getClock() in case of setting
955  *  extrapolated arrival times). This function is only called from
956  *  kart::finishedRace()
957  *  \param kart The kart that finished the race.
958  *  \param time Time at which the kart finished the race.
959  */
kartFinishedRace(const AbstractKart * kart,float time)960 void RaceManager::kartFinishedRace(const AbstractKart *kart, float time)
961 {
962     unsigned int id = kart->getWorldKartId();
963     int pos = kart->getPosition();
964 
965     assert(pos-1 >= 0);
966     assert(pos-1 < (int)m_kart_status.size());
967 
968     m_kart_status[id].m_last_score    = m_kart_status[id].m_score;
969 
970     // In follow the leader mode, the winner is actually the kart with
971     // position 2, so adjust the points (#points for leader do not matter)
972     WorldWithRank *wwr = dynamic_cast<WorldWithRank*>(World::getWorld());
973     if (wwr)
974         m_kart_status[id].m_score += wwr->getScoreForPosition(pos);
975     else
976     {
977         Log::error("RaceManager",
978                    "World with scores that is not a WorldWithRank??");
979     }
980 
981     m_kart_status[id].m_overall_time += time;
982     m_kart_status[id].m_last_time     = time;
983     m_num_finished_karts ++;
984     if(kart->getController()->isPlayerController())
985         m_num_finished_players++;
986 }   // kartFinishedRace
987 
988 //---------------------------------------------------------------------------------------------
989 /** \brief Rerun the same race again
990  * This is called after a race is finished, and it will adjust
991  * the number of points and the overall time before restarting the race.
992  */
rerunRace()993 void RaceManager::rerunRace()
994 {
995     // Subtract last score from all karts:
996     for(int i=0; i<m_num_karts; i++)
997     {
998         m_kart_status[i].m_score         = m_kart_status[i].m_last_score;
999         m_kart_status[i].m_overall_time -= m_kart_status[i].m_last_time;
1000     }
1001     World::getWorld()->reset(true /* restart */);
1002 }   // rerunRace
1003 
1004 //---------------------------------------------------------------------------------------------
1005 /** \brief Higher-level method to start a GP without having to care about
1006  *  the exact startup sequence
1007  */
startGP(const GrandPrixData & gp,bool from_overworld,bool continue_saved_gp)1008 void RaceManager::startGP(const GrandPrixData &gp, bool from_overworld,
1009                           bool continue_saved_gp)
1010 {
1011     StateManager::get()->enterGameState();
1012     setGrandPrix(gp);
1013     setupPlayerKartInfo();
1014     m_continue_saved_gp = continue_saved_gp;
1015 
1016     setMajorMode(RaceManager::MAJOR_MODE_GRAND_PRIX);
1017     startNew(from_overworld);
1018 }
1019 
1020 //---------------------------------------------------------------------------------------------
1021 /** \brief Higher-level method to start a GP without having to care about
1022  *  the exact startup sequence.
1023  * \param trackIdent Internal name of the track to race on
1024  * \param num_laps   Number of laps to race, or -1 if number of laps is
1025  *        not relevant in current mode
1026  */
startSingleRace(const std::string & track_ident,const int num_laps,bool from_overworld)1027 void RaceManager::startSingleRace(const std::string &track_ident,
1028                                   const int num_laps,
1029                                   bool from_overworld)
1030 {
1031     assert(!m_watching_replay);
1032     StateManager::get()->enterGameState();
1033 
1034     // In networking, make sure that the tracks screen is shown. This will
1035     // allow for a 'randomly pick track' animation to be shown while
1036     // world is loaded.
1037     // Disable until render gui during loading is bug free
1038     /*if (NetworkConfig::get()->isNetworking() &&
1039         NetworkConfig::get()->isClient()        )
1040     {
1041         // TODO: The enterGameState() call above deleted all GUIs, which
1042         // means even if the tracks screen is shown, it need to be recreated.
1043         // And we have to make sure that it is recreated as network version.
1044         TracksScreen *ts = TracksScreen::getInstance();
1045         if (GUIEngine::getCurrentScreen() != ts)
1046         {
1047             ts->setNetworkTracks();
1048             ts->push();
1049         }
1050     }*/
1051 
1052 
1053     setTrack(track_ident);
1054 
1055     if (num_laps != -1) setNumLaps( num_laps );
1056 
1057     setMajorMode(RaceManager::MAJOR_MODE_SINGLE);
1058 
1059     setCoinTarget( 0 ); // Might still be set from a previous challenge
1060 
1061     // if not in a network world, setup player karts
1062     if (!NetworkConfig::get()->isNetworking())
1063         setupPlayerKartInfo(); // do this setup player kart
1064 
1065     startNew(from_overworld);
1066 }   // startSingleRace
1067 
1068 //---------------------------------------------------------------------------------------------
1069 /** Fills up the remaining kart slots with AI karts.
1070  */
setupPlayerKartInfo()1071 void RaceManager::setupPlayerKartInfo()
1072 {
1073     computeRandomKartList();
1074 }   // setupPlayerKartInfo
1075 
1076 //---------------------------------------------------------------------------------------------
1077 /** \brief Function to start the race with only ghost kart(s) and watch.
1078  * \param trackIdent Internal name of the track to race on
1079  * \param num_laps   Number of laps to race, or -1 if number of laps is
1080  *        not relevant in current mode
1081  */
startWatchingReplay(const std::string & track_ident,const int num_laps)1082 void RaceManager::startWatchingReplay(const std::string &track_ident,
1083                                       const int num_laps)
1084 {
1085     assert(m_watching_replay && m_has_ghost_karts && !m_is_recording_race);
1086     StateManager::get()->enterGameState();
1087     setTrack(track_ident);
1088     setNumLaps(num_laps);
1089     setMajorMode(RaceManager::MAJOR_MODE_SINGLE);
1090     setCoinTarget(0);
1091     m_num_karts = ReplayPlay::get()->getNumGhostKart();
1092     m_kart_status.clear();
1093 
1094     Log::verbose("RaceManager", "%u ghost kart(s) for watching replay only\n",
1095         (unsigned int)m_num_karts);
1096 
1097     int init_gp_rank = 0;
1098 
1099     for(int i = 0; i < m_num_karts; i++)
1100     {
1101         m_kart_status.push_back(KartStatus(ReplayPlay::get()->getGhostKartName(i),
1102             i, -1, -1, init_gp_rank, KT_GHOST, HANDICAP_NONE));
1103         init_gp_rank ++;
1104     }
1105 
1106     m_track_number = 0;
1107     startNextRace();
1108 }   // startWatchingReplay
1109 
1110 //---------------------------------------------------------------------------------------------
configGrandPrixResultFromNetwork(NetworkString & ns)1111 void RaceManager::configGrandPrixResultFromNetwork(NetworkString& ns)
1112 {
1113     setMajorMode(MAJOR_MODE_GRAND_PRIX);
1114     class NetworkGrandPrixData : public GrandPrixData
1115     {
1116     public:
1117         NetworkGrandPrixData() : GrandPrixData()
1118             { setGroup(GrandPrixData::GP_STANDARD); }
1119         virtual std::vector<std::string>
1120             getTrackNames(const bool includeLocked=false) const
1121             { return m_tracks; }
1122         virtual unsigned int
1123             getNumberOfTracks(const bool includeLocked=false) const
1124             { return (unsigned int)m_tracks.size(); }
1125         void addNetworkTrack(const std::string& t) { m_tracks.push_back(t); }
1126     };
1127 
1128     NetworkGrandPrixData ngpd;
1129     unsigned int track_size = ns.getUInt8();
1130     unsigned int all_track_size = ns.getUInt8();
1131     assert(all_track_size > 0);
1132     m_track_number = all_track_size -1;
1133     for (unsigned i = 0; i < all_track_size; i++)
1134     {
1135         std::string t;
1136         ns.decodeString(&t);
1137         ngpd.addNetworkTrack(t);
1138     }
1139     while (all_track_size < track_size)
1140     {
1141         ngpd.addNetworkTrack("");
1142         all_track_size++;
1143     }
1144 
1145     m_tracks = ngpd.getTrackNames();
1146     // For result screen we only need current lap and reserve
1147     m_num_laps.resize(track_size, m_num_laps[0]);
1148     m_reverse_track.resize(track_size, m_reverse_track[0]);
1149 
1150     m_grand_prix = ngpd;
1151     unsigned int player_size = ns.getUInt8();
1152     assert(player_size == m_kart_status.size());
1153     for (unsigned i = 0; i < player_size; i++)
1154     {
1155         int last_score = ns.getUInt32();
1156         int cur_score = ns.getUInt32();
1157         float overall_time = ns.getFloat();
1158         m_kart_status[i].m_last_score = last_score;
1159         m_kart_status[i].m_score = cur_score;
1160         m_kart_status[i].m_overall_time = overall_time;
1161         m_kart_status[i].m_gp_rank = i;
1162     }
1163 }   // configGrandPrixResultFromNetwork
1164 
1165 //---------------------------------------------------------------------------------------------
clearNetworkGrandPrixResult()1166 void RaceManager::clearNetworkGrandPrixResult()
1167 {
1168     if (m_major_mode != MAJOR_MODE_GRAND_PRIX)
1169         return;
1170     setMajorMode(MAJOR_MODE_SINGLE);
1171     m_grand_prix = GrandPrixData();
1172     m_track_number = 0;
1173     m_tracks.clear();
1174     m_num_laps.clear();
1175     m_reverse_track.clear();
1176 
1177 }   // clearNetworkGrandPrixResult
1178 
1179 //---------------------------------------------------------------------------------------------
1180 /** Returns a (translated) name of a minor race mode.
1181  *  \param mode Minor race mode.
1182  */
getNameOf(const MinorRaceModeType mode)1183 const core::stringw RaceManager::getNameOf(const MinorRaceModeType mode)
1184 {
1185     switch (mode)
1186     {
1187         //I18N: Game mode
1188         case MINOR_MODE_NORMAL_RACE:    return _("Normal Race");
1189         //I18N: Game mode
1190         case MINOR_MODE_TIME_TRIAL:     return _("Time Trial");
1191         //I18N: Game mode
1192         case MINOR_MODE_FOLLOW_LEADER:  return _("Follow the Leader");
1193         //I18N: Game mode
1194         case MINOR_MODE_3_STRIKES:      return _("3 Strikes Battle");
1195         //I18N: Game mode
1196         case MINOR_MODE_FREE_FOR_ALL:   return _("Free-For-All");
1197         //I18N: Game mode
1198         case MINOR_MODE_CAPTURE_THE_FLAG: return _("Capture The Flag");
1199         //I18N: Game mode
1200         case MINOR_MODE_EASTER_EGG:     return _("Egg Hunt");
1201         //I18N: Game mode
1202         case MINOR_MODE_SOCCER:         return _("Soccer");
1203         default: assert(false); return L"";
1204     }
1205 }   // getNameOf
1206 
1207 //---------------------------------------------------------------------------------------------
1208 /** Returns the specified difficulty as a string. */
getDifficultyName(Difficulty diff) const1209 core::stringw RaceManager::getDifficultyName(Difficulty diff) const
1210 {
1211     switch (diff)
1212     {
1213         case RaceManager::DIFFICULTY_EASY:   return _("Novice");   break;
1214         case RaceManager::DIFFICULTY_MEDIUM: return _("Intermediate"); break;
1215         case RaceManager::DIFFICULTY_HARD:   return _("Expert");   break;
1216         case RaceManager::DIFFICULTY_BEST:   return _("SuperTux");   break;
1217         default:  assert(false);
1218     }
1219     return "";
1220 }   // getDifficultyName
1221