stk-code_catmod/src/race/race_manager.hpp
2019-04-17 17:05:34 +02:00

927 lines
39 KiB
C++

//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006-2015 SuperTuxKart-Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_RACEMANAGER_HPP
#define HEADER_RACEMANAGER_HPP
/**
* \defgroup race
* Contains the race information that is conceptually above what you can find
* in group Modes. Handles highscores, grands prix, number of karts, which
* track was selected, etc.
*/
#include <vector>
#include <algorithm>
#include <string>
#include "network/remote_kart_info.hpp"
#include "race/grand_prix_data.hpp"
#include "utils/translation.hpp"
#include "utils/vec3.hpp"
class AbstractKart;
class NetworkString;
class SavedGrandPrix;
class Track;
static const std::string IDENT_STD ("STANDARD" );
static const std::string IDENT_TTRIAL ("STD_TIMETRIAL" );
static const std::string IDENT_FTL ("FOLLOW_LEADER" );
static const std::string IDENT_STRIKES ("BATTLE_3_STRIKES");
static const std::string IDENT_FFA ("BATTLE_FFA" );
static const std::string IDENT_CTF ("BATTLE_CTF" );
static const std::string IDENT_EASTER ("EASTER_EGG_HUNT" );
static const std::string IDENT_SOCCER ("SOCCER" );
static const std::string IDENT_GHOST ("GHOST" );
static const std::string IDENT_OVERWORLD("OVERWORLD" );
static const std::string IDENT_CUTSCENE ("CUTSCENE" );
/**
* The race manager has two functions:
* 1) it stores information about the race the user selected (e.g. number
* of karts, track, race mode etc.). Most of the values are just stored
* from the menus, and just read back, except for GP mode (the race
* manager stores the GP information, but World queries only track
* and number of laps, so in case of GP this information is taken from
* the GrandPrix object), and local player information (number of local
* players, and selected karts).
* Information about player karts (which player selected which kart,
* player ids) is stored in a RemoteKartInfo structure and used later
* to initialise the KartStatus array (startNew()). The KartStatus array
* stores information about all karts (player and AI), and is used to
* determine the order in which karts are started (see startNextRace()).
* 2) when a race is started, it creates the world, and keeps track of
* score during the race. When a race is finished, it deletes the world,
* and (depending on race mode) starts the next race by creating a new
* world.
* Information in the RaceManager is considered to be 'more static', sometimes
* the world has similar functions showing the current state. E.g.: the
* race manager keeps track of the number of karts with which the race was
* started, while world keeps track of the number of karts currently in the
* race (consider a race mode like follow the leader where karts can get
* eliminated, but still the RaceManager has to accumulate points for those
* karts).
* The race manager handles all race types as a kind of grand prix. E.g.:
* a quick race is basically a GP with only one track (so the race manager
* keeps track of scores even though no scores are used in a quick race).
*
* \ingroup race
*/
class RaceManager
{
public:
/** The major types or races supported in STK
*/
enum MajorRaceModeType
{
MAJOR_MODE_GRAND_PRIX = 0,
MAJOR_MODE_SINGLE
};
// quick method to tell the difference between battle modes and race modes
// think of it like a bitmask, but done in decimal to avoid endianness
// issues
#define LINEAR_RACE(ID, COUNT_LAPSES) (1000+ID+100*COUNT_LAPSES)
#define BATTLE_ARENA(ID) (2000+ID)
#define EASTER_EGG(ID) (3000+ID)
#define MISC(ID) (4000+ID)
// ------------------------------------------------------------------------
/** Minor variants to the major types of race.
* Make sure to use the 'LINEAR_RACE/BATTLE_ARENA' macros. */
enum MinorRaceModeType
{
MINOR_MODE_NONE = -1,
MINOR_MODE_NORMAL_RACE = LINEAR_RACE(0, true),
MINOR_MODE_TIME_TRIAL = LINEAR_RACE(1, true),
MINOR_MODE_FOLLOW_LEADER = LINEAR_RACE(2, false),
MINOR_MODE_3_STRIKES = BATTLE_ARENA(0),
MINOR_MODE_FREE_FOR_ALL = BATTLE_ARENA(1),
MINOR_MODE_CAPTURE_THE_FLAG = BATTLE_ARENA(2),
MINOR_MODE_SOCCER = BATTLE_ARENA(3),
MINOR_MODE_EASTER_EGG = EASTER_EGG(0),
MINOR_MODE_OVERWORLD = MISC(0),
MINOR_MODE_TUTORIAL = MISC(1),
MINOR_MODE_CUTSCENE = MISC(2)
};
// ------------------------------------------------------------------------
/** True if the AI should have additional abbilities, e.g.
* nolok will get special bubble gums in the final challenge. */
enum AISuperPower
{
SUPERPOWER_NONE = 0,
SUPERPOWER_NOLOK_BOSS = 1
};
// ------------------------------------------------------------------------
/** Returns a string identifier for each minor race mode.
* \param mode Minor race mode.
*/
static const std::string& getIdentOf(const MinorRaceModeType mode)
{
switch (mode)
{
case MINOR_MODE_NORMAL_RACE: return IDENT_STD;
case MINOR_MODE_TIME_TRIAL: return IDENT_TTRIAL;
case MINOR_MODE_FOLLOW_LEADER: return IDENT_FTL;
case MINOR_MODE_3_STRIKES: return IDENT_STRIKES;
case MINOR_MODE_FREE_FOR_ALL: return IDENT_FFA;
case MINOR_MODE_CAPTURE_THE_FLAG: return IDENT_CTF;
case MINOR_MODE_EASTER_EGG: return IDENT_EASTER;
case MINOR_MODE_SOCCER: return IDENT_SOCCER;
default: assert(false);
return IDENT_STD; // stop compiler warning
}
} // getIdentOf
// ------------------------------------------------------------------------
/** Returns the icon for a minor race mode.
* \param mode Minor race mode.
*/
static const char* getIconOf(const MinorRaceModeType mode)
{
switch (mode)
{
case MINOR_MODE_NORMAL_RACE: return "/gui/icons/mode_normal.png";
case MINOR_MODE_TIME_TRIAL: return "/gui/icons/mode_tt.png";
case MINOR_MODE_FOLLOW_LEADER: return "/gui/icons/mode_ftl.png";
case MINOR_MODE_3_STRIKES: return "/gui/icons/mode_3strikes.png";
case MINOR_MODE_FREE_FOR_ALL: return "/gui/icons/weapons.png";
case MINOR_MODE_CAPTURE_THE_FLAG: return "/gui/icons/weapons.png";
case MINOR_MODE_EASTER_EGG: return "/gui/icons/mode_easter.png";
case MINOR_MODE_SOCCER: return "/gui/icons/mode_soccer.png";
default: assert(false); return NULL;
}
} // getIconOf
// ------------------------------------------------------------------------
/** Returns a (translated) name of a minor race mode.
* \param mode Minor race mode.
*/
static const core::stringw getNameOf(const MinorRaceModeType mode)
{
switch (mode)
{
//I18N: Game mode
case MINOR_MODE_NORMAL_RACE: return _("Normal Race");
//I18N: Game mode
case MINOR_MODE_TIME_TRIAL: return _("Time Trial");
//I18N: Game mode
case MINOR_MODE_FOLLOW_LEADER: return _("Follow the Leader");
//I18N: Game mode
case MINOR_MODE_3_STRIKES: return _("3 Strikes Battle");
//I18N: Game mode
case MINOR_MODE_FREE_FOR_ALL: return _("Free-For-All");
//I18N: Game mode
case MINOR_MODE_CAPTURE_THE_FLAG: return _("Capture The Flag");
//I18N: Game mode
case MINOR_MODE_EASTER_EGG: return _("Egg Hunt");
//I18N: Game mode
case MINOR_MODE_SOCCER: return _("Soccer");
default: assert(false); return L"";
}
} // getNameOf
// ------------------------------------------------------------------------
/** Returns if the currently set minor game mode can be used by the AI. */
bool hasAI()
{
switch (m_minor_mode)
{
case MINOR_MODE_NORMAL_RACE: return true;
case MINOR_MODE_TIME_TRIAL: return true;
case MINOR_MODE_FOLLOW_LEADER: return true;
case MINOR_MODE_3_STRIKES: return true;
case MINOR_MODE_FREE_FOR_ALL: return false;
case MINOR_MODE_CAPTURE_THE_FLAG: return false;
case MINOR_MODE_EASTER_EGG: return false;
case MINOR_MODE_SOCCER: return true;
default: assert(false); return false;
}
} // hasAI
// ------------------------------------------------------------------------
/** Returns the minor mode id from a string identifier. This function is
* used from challenge_data, which reads the mode from a challenge file.
* \param name The name of the minor mode.
*/
static const MinorRaceModeType getModeIDFromInternalName(
const std::string &name)
{
if (name==IDENT_STD ) return MINOR_MODE_NORMAL_RACE;
else if (name==IDENT_TTRIAL ) return MINOR_MODE_TIME_TRIAL;
else if (name==IDENT_FTL ) return MINOR_MODE_FOLLOW_LEADER;
else if (name==IDENT_STRIKES) return MINOR_MODE_3_STRIKES;
else if (name==IDENT_FFA) return MINOR_MODE_FREE_FOR_ALL;
else if (name==IDENT_CTF) return MINOR_MODE_CAPTURE_THE_FLAG;
else if (name==IDENT_EASTER ) return MINOR_MODE_EASTER_EGG;
else if (name==IDENT_SOCCER) return MINOR_MODE_SOCCER;
assert(0);
return MINOR_MODE_NONE;
}
#undef LINEAR_RACE
#undef BATTLE_ARENA
#undef MISC
/** Game difficulty. */
enum Difficulty { DIFFICULTY_EASY = 0,
DIFFICULTY_FIRST = DIFFICULTY_EASY,
DIFFICULTY_MEDIUM,
DIFFICULTY_HARD,
DIFFICULTY_BEST,
DIFFICULTY_LAST = DIFFICULTY_BEST,
DIFFICULTY_COUNT,
DIFFICULTY_NONE};
/** Different kart types: A local player, a player connected via network,
* an AI kart, the leader kart (currently not used), a ghost kart and
* spare tire karts which allow gain life in battle mode */
enum KartType { KT_PLAYER, KT_NETWORK_PLAYER, KT_AI, KT_LEADER,
KT_GHOST, KT_SPARE_TIRE };
private:
bool m_started_from_overworld;
public:
/** This data structure accumulates kart data and race result data from
* each race. */
struct KartStatus
{
/** The kart identifier. */
std::string m_ident;
/** For networked karts. */
std::string m_player_name;
// Score for this kart. */
int m_score;
/** Needed for restart race, and for race results GUI. */
int m_last_score;
/** Sum of times of all races. */
float m_overall_time;
/** Needed for restart. */
float m_last_time;
/** Kart type: AI, player, network player etc. */
KartType m_kart_type;
/** Player controling the kart, for AI: -1 */
int m_local_player_id;
/** Global ID of player. */
int m_global_player_id;
/** In GPs, at the end, will hold the overall rank of this kart
* (0<=m_gp_rank < num_karts-1). */
int m_gp_rank;
/** Boosted status (AI only). */
bool m_boosted_ai;
/** The difficulty for this player. */
PerPlayerDifficulty m_difficulty;
KartStatus(const std::string& ident, const int& prev_finish_pos,
int local_player_id, int global_player_id,
int init_gp_rank, KartType kt,
PerPlayerDifficulty difficulty) :
m_ident(ident), m_score(0), m_last_score(0),
m_overall_time(0.0f), m_last_time(0.0f),
m_kart_type(kt),
m_local_player_id(local_player_id),
m_global_player_id(global_player_id),
m_gp_rank(init_gp_rank), m_difficulty(difficulty)
{ m_boosted_ai = false; }
}; // KartStatus
private:
/** The kart status data for each kart. */
std::vector<KartStatus> m_kart_status;
/** The selected difficulty. */
Difficulty m_difficulty;
/** The major mode (single race, GP). */
MajorRaceModeType m_major_mode;
/** The minor mode (race, time trial, ftl, battle mode). */
MinorRaceModeType m_minor_mode;
/** Stores remote kart information about all player karts. */
std::vector<RemoteKartInfo> m_player_karts;
std::vector<std::string> m_tracks;
/** Number of local players. */
unsigned int m_num_local_players;
/** The number of laps for each track of a GP (only one element
* is used if only a single track is used. */
std::vector<int> m_num_laps;
/** Whether a track should be reversed */
std::vector<bool> m_reverse_track;
/** The list of default AI karts to use. This is from the command line. */
std::vector<std::string> m_default_ai_list;
/** If set, specifies which kart to use for AI(s) */
std::string m_ai_kart_override;
AISuperPower m_ai_superpower;
/** The list of AI karts to use. This is stored here so that the
* same list of AIs is used for all tracks of a GP. */
std::vector<std::string> m_ai_kart_list;
int m_track_number;
GrandPrixData m_grand_prix;
SavedGrandPrix* m_saved_gp;
int m_num_karts;
unsigned int m_num_ghost_karts;
unsigned int m_num_spare_tire_karts;
unsigned int m_num_finished_karts;
unsigned int m_num_finished_players;
unsigned m_flag_return_ticks;
unsigned m_flag_deactivated_ticks;
int m_coin_target;
float m_time_target;
int m_goal_target;
int m_hit_capture_limit;
void startNextRace(); // start a next race
friend bool operator< (const KartStatus& left, const KartStatus& right)
{
return (left.m_score < right.m_score) ||
(left.m_score == right.m_score &&
left.m_overall_time > right.m_overall_time);
}
bool m_have_kart_last_position_on_overworld;
Vec3 m_kart_last_position_on_overworld;
/** Determines if saved GP should be continued or not*/
bool m_continue_saved_gp;
bool m_is_recording_race;
bool m_has_ghost_karts;
bool m_watching_replay;
public:
RaceManager();
~RaceManager();
void reset();
void setPlayerKart(unsigned int player_id, const std::string &kart_name);
void setPlayerKart(unsigned int player_id,
const RemoteKartInfo& ki);
/** Sets additional information for a player to indicate which team it belong to
*/
void setKartTeam(unsigned int player_id, KartTeam team);
/** Sets the per-player difficulty for a player.
*/
void setPlayerDifficulty(unsigned int player_id, PerPlayerDifficulty difficulty);
/** In case of non GP mode set the track to use.
* \param track Pointer to the track to use.
*/
void setTrack(const std::string& track);
/** \brief Returns the kart with a given GP rank (or NULL if no such
* kart exists).
* \param n Rank (0<=n<num_karts) to look for.
*/
const AbstractKart* getKartWithGPRank(unsigned int n);
/** \return the GP rank of a local player, or -1 if the given player ID
* doesn't exist */
int getLocalPlayerGPRank(const int playerID) const;
/** Sort karts and update the m_gp_rank KartStatus member, in preparation
* for future calls to RaceManager::getKartGPRank or
* RaceManager::getKartWithGPRank
*/
void computeGPRanks();
/** \brief Sets the difficulty.
* \param diff Difficulty.
*/
void setDifficulty(Difficulty diff);
static Difficulty convertDifficulty(const std::string &difficulty);
void startNew(bool from_overworld);
void next();
void rerunRace();
void exitRace(bool delete_world=true);
void startGP(const GrandPrixData &gp, bool from_overworld,
bool continue_saved_gp);
void saveGP();
void startSingleRace(const std::string &track_ident, const int num_laps,
bool from_overworld);
void startWatchingReplay(const std::string &track_ident, const int num_laps);
void setupPlayerKartInfo();
void kartFinishedRace(const AbstractKart* kart, float time);
void setNumPlayers(int players, int local_players=-1);
void setDefaultAIKartList(const std::vector<std::string> &ai_list);
void computeRandomKartList();
// ------------------------------------------------------------------------
bool hasTimeTarget() const { return m_time_target > 0.0f; }
// ------------------------------------------------------------------------
void setMaxGoal(int max_goal)
{
m_time_target = 0.0f;
m_goal_target = max_goal;
} // setMaxGoal
// ------------------------------------------------------------------------
int getMaxGoal(){ return m_goal_target; }
// ------------------------------------------------------------------------
void setCoinTarget(int num) { m_coin_target = num; }
// ------------------------------------------------------------------------
void setGrandPrix(const GrandPrixData &gp)
{
m_grand_prix = gp;
setCoinTarget(0);
} // setGrandPrix
// ------------------------------------------------------------------------
void setAIKartOverride(const std::string& kart)
{
m_ai_kart_override = kart;
} // setAIKartOverride
// ------------------------------------------------------------------------
void setAISuperPower(AISuperPower superpower)
{
m_ai_superpower = superpower;
} // setAISuperPower
// ------------------------------------------------------------------------
AISuperPower getAISuperPower() const { return m_ai_superpower; }
// ------------------------------------------------------------------------
void setNumLaps(int num)
{
m_num_laps.clear();
m_num_laps.push_back(num);
} // setNumLaps
// ------------------------------------------------------------------------
void setReverseTrack(bool r_t)
{
m_reverse_track.clear();
m_reverse_track.push_back(r_t);
} // setReverseTrack
// ------------------------------------------------------------------------
void setMajorMode(MajorRaceModeType mode) { m_major_mode = mode; }
// ------------------------------------------------------------------------
void setMinorMode(MinorRaceModeType mode)
{
m_minor_mode = mode;
} // setMinorMode
// ------------------------------------------------------------------------
void setNumKarts(int num)
{
m_num_karts = num;
m_ai_kart_override = "";
m_ai_superpower = SUPERPOWER_NONE;
} // setNumKarts
// ------------------------------------------------------------------------
void setTimeTarget(float time)
{
m_goal_target = 0;
m_time_target = time;
} // setTimeTarget
// ------------------------------------------------------------------------
RemoteKartInfo& getKartInfo(unsigned int n)
{
return m_player_karts[n];
} // getKartInfo
// ------------------------------------------------------------------------
unsigned int getNumLocalPlayers() const
{
return m_num_local_players;
} // getNumLocalPlayers
// ------------------------------------------------------------------------
/** Returns true if the split screen display leaves an empty space that
* can be used to display the minimap.
*/
bool getIfEmptyScreenSpaceExists() const
{
const float sqrt_num_players = sqrtf((float)getNumLocalPlayers());
const int rows = (int)ceil(sqrt_num_players);
const int cols = (int)round(sqrt_num_players);
const int total_spaces = rows * cols;
return (total_spaces - getNumLocalPlayers() > 0);
} // getIfEmptyScreenSpaceExists
// ------------------------------------------------------------------------
/** Returns the selected number of karts (selected number of players and
* AI karts. */
unsigned int getNumberOfKarts() const {return m_num_karts; }
// ------------------------------------------------------------------------
unsigned int getNumberOfAIKarts() const
{
return (unsigned int)m_ai_kart_list.size();
} // getNumberOfAIKarts
// ------------------------------------------------------------------------
unsigned int getNumNonGhostKarts() const
{ return m_num_karts - m_num_ghost_karts; }
// ------------------------------------------------------------------------
MajorRaceModeType getMajorMode() const { return m_major_mode; }
// ------------------------------------------------------------------------
MinorRaceModeType getMinorMode() const { return m_minor_mode; }
// ------------------------------------------------------------------------
std::string getMinorModeName() const
{
switch (m_minor_mode)
{
case MINOR_MODE_NORMAL_RACE: return "normal";
case MINOR_MODE_TIME_TRIAL: return "time-trial";
case MINOR_MODE_FOLLOW_LEADER: return "follow-the-leader";
case MINOR_MODE_3_STRIKES: return "battle";
case MINOR_MODE_FREE_FOR_ALL: return "ffa";
case MINOR_MODE_CAPTURE_THE_FLAG: return "ctf";
case MINOR_MODE_EASTER_EGG: return "egg-hunt";
case MINOR_MODE_SOCCER: return "soccer";
default: assert(false); return "";
}
}
// ------------------------------------------------------------------------
unsigned int getNumPlayers() const
{
return (unsigned int) m_player_karts.size();
} // getNumPlayers
// ------------------------------------------------------------------------
/** \brief Returns the number lf laps.
* In case of FTL or battle mode always return 9999, since they don't
* have laps. This avoids problems in FTL GP, since in this case no laps
* would be set (otherwise we would need many more tests in calls to
* getNumLaps).
*/
int getNumLaps() const
{
if(modeHasLaps())
return m_num_laps[m_track_number];
// else
return 9999;
} // getNumLaps
// ------------------------------------------------------------------------
/** \return whether the track should be reversed */
bool getReverseTrack() const { return m_reverse_track[m_track_number]; }
// ------------------------------------------------------------------------
/** Returns the difficulty. */
Difficulty getDifficulty() const { return m_difficulty; }
// ------------------------------------------------------------------------
/** Returns the specified difficulty as a string. */
std::string getDifficultyAsString(Difficulty diff) const
{
switch(diff)
{
case RaceManager::DIFFICULTY_EASY: return "easy"; break;
case RaceManager::DIFFICULTY_MEDIUM: return "medium"; break;
case RaceManager::DIFFICULTY_HARD: return "hard"; break;
case RaceManager::DIFFICULTY_BEST: return "best"; break;
default: assert(false);
}
return "";
} // getDifficultyAsString
// ------------------------------------------------------------------------
/** Returns the specified difficulty as a string. */
core::stringw getDifficultyName(Difficulty diff) const
{
switch (diff)
{
case RaceManager::DIFFICULTY_EASY: return _("Novice"); break;
case RaceManager::DIFFICULTY_MEDIUM: return _("Intermediate"); break;
case RaceManager::DIFFICULTY_HARD: return _("Expert"); break;
case RaceManager::DIFFICULTY_BEST: return _("SuperTux"); break;
default: assert(false);
}
return "";
} // getDifficultyName
// ------------------------------------------------------------------------
const std::string& getTrackName() const { return m_tracks[m_track_number];}
// ------------------------------------------------------------------------
const GrandPrixData& getGrandPrix() const { return m_grand_prix; }
// ------------------------------------------------------------------------
unsigned int getFinishedKarts() const { return m_num_finished_karts; }
// ------------------------------------------------------------------------
unsigned int getFinishedPlayers() const { return m_num_finished_players; }
// ------------------------------------------------------------------------
int getKartGPRank(const int kart_id)const
{
return m_kart_status[kart_id].m_gp_rank;
} // getKartGPRank
// ------------------------------------------------------------------------
const std::string& getKartIdent(int kart) const
{
return m_kart_status[kart].m_ident;
} // getKartIdent
// ------------------------------------------------------------------------
int getKartScore(int krt) const { return m_kart_status[krt].m_score; }
// ------------------------------------------------------------------------
int getKartPrevScore(int krt) const
{
return m_kart_status[krt].m_last_score;
} // getKartPrevScore
// ------------------------------------------------------------------------
int getKartLocalPlayerId(int k) const
{
return m_kart_status[k].m_local_player_id;
} // getKartLocalPlayerId
// ------------------------------------------------------------------------
int getKartGlobalPlayerId(int k) const
{
return m_kart_status[k].m_global_player_id;
} // getKartGlobalPlayerId
// ------------------------------------------------------------------------
float getOverallTime(int kart) const
{
return m_kart_status[kart].m_overall_time;
} // getOverallTime
// ------------------------------------------------------------------------
float getKartRaceTime(int kart) const
{
return m_kart_status[kart].m_last_time;
} // getKartRaceTime
// ------------------------------------------------------------------------
KartType getKartType(int kart) const
{
return m_kart_status[kart].m_kart_type;
} // getKartType
// ------------------------------------------------------------------------
PerPlayerDifficulty getPlayerDifficulty(int kart) const
{
return m_kart_status[kart].m_difficulty;
} // getPlayerDifficulty
// ------------------------------------------------------------------------
bool hasBoostedAI(int kart) const
{
return m_kart_status[kart].m_boosted_ai;
} // getKartRaceTime
// ------------------------------------------------------------------------
int getCoinTarget() const { return m_coin_target; }
// ------------------------------------------------------------------------
float getTimeTarget() const { return m_time_target; }
// ------------------------------------------------------------------------
int getTrackNumber() const { return m_track_number; }
// ------------------------------------------------------------------------
int getNumOfTracks() const { return (int)m_tracks.size(); }
// ------------------------------------------------------------------------
/** Returns the list of AI karts to use. Used for networking, and for
* the --ai= command line option. */
const std::vector<std::string>& getAIKartList() const
{
return m_ai_kart_list;
} // getAIKartList
// ------------------------------------------------------------------------
/** \brief get information about current mode (returns true if 'mode' is of
* linear races type) */
bool isLinearRaceMode() const
{
const int id = (int)m_minor_mode;
// info is stored in its ID for conveniance, see the macros LINEAR_RACE
// and BATTLE_ARENA above for exact meaning.
if(id > 999 && id < 2000) return true;
else return false;
} // isLinearRaceMode
// ------------------------------------------------------------------------
/** \brief get information about given mode (returns true if 'mode' is of
* linear races type) */
bool isLinearRaceMode(const MinorRaceModeType mode) const
{
const int id = (int)mode;
// info is stored in its ID for conveniance, see the macros LINEAR_RACE
// and BATTLE_ARENA above for exact meaning.
if(id > 999 && id < 2000) return true;
else return false;
} // isLinearRaceMode
// ------------------------------------------------------------------------
/** \brief Returns true if the current mode is a battle mode. */
bool isBattleMode() const
{
const int id = (int)m_minor_mode;
// This uses the numerical id of the mode, see the macros
// LINEAR_RACE and BATTLE_ARENA above for exact meaning.
if (id >= 2000 && id <= 2002) return true;
else return false;
} // isBattleMode
// ------------------------------------------------------------------------
/** \brief Returns true if the current mode is a soccer mode. */
bool isSoccerMode() const
{
const int id = (int)m_minor_mode;
// This uses the numerical id of the mode, see the macros
// LINEAR_RACE and BATTLE_ARENA above for exact meaning.
if (id == 2003) return true;
else return false;
} // isSoccerMode
// ------------------------------------------------------------------------
bool isTutorialMode() const
{
return m_minor_mode == MINOR_MODE_TUTORIAL;
} // isTutorialMode
// ------------------------------------------------------------------------
bool isFollowMode() const
{
return m_minor_mode == MINOR_MODE_FOLLOW_LEADER;
}
// ------------------------------------------------------------------------
bool isEggHuntMode() const
{
return m_minor_mode == MINOR_MODE_EASTER_EGG;
} // isEggHuntMode
// ------------------------------------------------------------------------
bool isTimeTrialMode() const
{
return m_minor_mode == MINOR_MODE_TIME_TRIAL;
} // isTimeTrialMode
// ------------------------------------------------------------------------
/** \brief Returns the number of second's decimals to display */
int currentModeTimePrecision() const
{
if (isEggHuntMode() || isTimeTrialMode())
return 3;//display milliseconds
return 2;//display centiseconds
} // currentModeTimePrecision
// ------------------------------------------------------------------------
/** \brief Returns true if the current mode has laps. */
bool modeHasLaps() const
{
if (!isLinearRaceMode()) return false;
const int id = (int)m_minor_mode;
// See meaning of IDs above
const int answer = (id-1000)/100;
return answer!=0;
} // modeHasLaps
// ------------------------------------------------------------------------
/** Returns true if the currently selected minor mode has highscores. */
bool modeHasHighscores()
{
//FIXME: this information is duplicated. RaceManager knows about it,
// and each World may set m_use_highscores to true or false.
// The reason for this duplication is that we might want to know
// whether to display highscores without creating a World.
return !isBattleMode() &&
!isSoccerMode() &&
m_minor_mode != MINOR_MODE_FOLLOW_LEADER;
} // modeHasHighscore
// ------------------------------------------------------------------------
bool raceWasStartedFromOverworld() const
{
return m_started_from_overworld;
} // raceWasStartedFromOverworld
// ------------------------------------------------------------------------
/** \name Callbacks from the race classes
* These methods are to be used by the classes that manage the various
* races, to let the race manager know about current status
*/
bool allPlayerFinished() const
{
return m_num_finished_players == m_player_karts.size();
} // allPlayerFinished
// ------------------------------------------------------------------------
/** Sets the AI to use. This is used in networking mode to set the karts
* that will be used by the server to the client. It will take precedence
* over the random selection. */
void setAIKartList(const std::vector<std::string>& rkl)
{
m_ai_kart_list = rkl;
} // setAIKartList
// ------------------------------------------------------------------------
bool haveKartLastPositionOnOverworld()
{
return m_have_kart_last_position_on_overworld;
} // haveKartLastPositionOnOverworld
// ------------------------------------------------------------------------
void setKartLastPositionOnOverworld(const Vec3 &pos)
{
m_have_kart_last_position_on_overworld = true;
m_kart_last_position_on_overworld = pos;
} // setKartLastPositionOnOverworld
// ------------------------------------------------------------------------
void clearKartLastPositionOnOverworld()
{
m_have_kart_last_position_on_overworld = false;
} // clearKartLastPositionOnOverworld
// ------------------------------------------------------------------------
Vec3 getKartLastPositionOnOverworld()
{
return m_kart_last_position_on_overworld;
} // getKartLastPositionOnOverworld
// ------------------------------------------------------------------------
void setRecordRace(bool record)
{
m_is_recording_race = record;
} // setRecordRace
// ------------------------------------------------------------------------
void setRaceGhostKarts(bool ghost)
{
m_has_ghost_karts = ghost;
} // setRaceGhostKarts
// ------------------------------------------------------------------------
void setWatchingReplay(bool watch)
{
m_watching_replay = watch;
} // setWatchingReplay
// ------------------------------------------------------------------------
bool isRecordingRace() const
{
return m_is_recording_race;
} // isRecordingRace
// ------------------------------------------------------------------------
bool hasGhostKarts() const
{
return m_has_ghost_karts;
} // hasGhostKarts
// ------------------------------------------------------------------------
bool isWatchingReplay() const
{
return m_watching_replay;
} // isWatchingReplay
// ------------------------------------------------------------------------
void addSpareTireKart(const std::string& name)
{
m_kart_status.push_back(KartStatus(name, 0, -1, -1,
-1, KT_SPARE_TIRE, PLAYER_DIFFICULTY_NORMAL));
m_num_spare_tire_karts++;
m_num_karts++;
} // addSpareTireKart
// ------------------------------------------------------------------------
void setSpareTireKartNum(unsigned int i)
{
m_num_spare_tire_karts = i;
} // setSpareTireKartNum
// ------------------------------------------------------------------------
unsigned int getNumSpareTireKarts() const
{
return m_num_spare_tire_karts;
} // getNumSpareTireKarts
// ------------------------------------------------------------------------
void configGrandPrixResultFromNetwork(NetworkString& ns);
// ------------------------------------------------------------------------
void clearNetworkGrandPrixResult();
// ------------------------------------------------------------------------
void setHitCaptureTime(int hc, float time)
{
m_hit_capture_limit = hc;
m_time_target = time;
}
// ------------------------------------------------------------------------
int getHitCaptureLimit() const { return m_hit_capture_limit; }
// ------------------------------------------------------------------------
bool teamEnabled() const
{
return m_minor_mode == MINOR_MODE_SOCCER ||
m_minor_mode == MINOR_MODE_CAPTURE_THE_FLAG;
}
// ------------------------------------------------------------------------
void setFlagReturnTicks(unsigned ticks) { m_flag_return_ticks = ticks; }
// ------------------------------------------------------------------------
unsigned getFlagReturnTicks() const { return m_flag_return_ticks; }
// ------------------------------------------------------------------------
void setFlagDeactivatedTicks(unsigned ticks)
{ m_flag_deactivated_ticks = ticks; }
// ------------------------------------------------------------------------
unsigned getFlagDeactivatedTicks() const
{ return m_flag_deactivated_ticks; }
// ------------------------------------------------------------------------
/** Whether the current game mode allow live joining even the current game
*. started in network*/
bool supportsLiveJoining() const
{
return m_minor_mode == MINOR_MODE_SOCCER ||
m_minor_mode == MINOR_MODE_CAPTURE_THE_FLAG ||
m_minor_mode == MINOR_MODE_FREE_FOR_ALL;
}
}; // RaceManager
extern RaceManager *race_manager;
#endif
/* EOF */