1 // 2 // SuperTuxKart - a fun racing game with go-kart 3 // Copyright (C) 2004-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_WORLD_HPP 20 #define HEADER_WORLD_HPP 21 22 /** 23 * \defgroup modes 24 * Contains the logic for the various game modes (race, follow the leader, 25 * battle, etc.) 26 */ 27 28 #include <cstring> 29 #include <limits> 30 #include <map> 31 #include <memory> 32 #include <vector> 33 #include <stdexcept> 34 35 #include "graphics/weather.hpp" 36 #include "modes/world_status.hpp" 37 #include "race/highscores.hpp" 38 #include "states_screens/race_gui_base.hpp" 39 #include "states_screens/state_manager.hpp" 40 #include "utils/random_generator.hpp" 41 #include "utils/stk_process.hpp" 42 43 #include "LinearMath/btTransform.h" 44 45 class AbstractKart; 46 class BareNetworkString; 47 class btRigidBody; 48 class Controller; 49 class ItemState; 50 class PhysicalObject; 51 class STKPeer; 52 53 namespace Scripting 54 { 55 class ScriptEngine; 56 } 57 58 namespace irr 59 { 60 namespace scene { class ISceneNode; } 61 } 62 63 class AbortWorldUpdateException : public std::runtime_error 64 { 65 public: AbortWorldUpdateException()66 AbortWorldUpdateException() : std::runtime_error("race abort") { }; 67 }; 68 69 /** 70 * \brief base class for all game modes 71 * This class is responsible for running the actual race. A world is created 72 * by the race manager on the start of each race (so a new world is created 73 * for each race of a Grand Prix). It creates the 74 * physics, loads the track, creates all karts, and initialises the race 75 * specific managers (ItemManager, ProjectilManager, highscores, ...). 76 * It uses the information from the race manager to get information like 77 * what and how many karts, track to load etc. This class does not really 78 * know about Grand Prixs, a GP is created 79 * It maintains the race clock, and updates all karts, herings etc. during 80 * the race. 81 * Special game modes (e.g. follow the leader) are currently integrated in 82 * this world, see e.g. updateRaceStatus where the world clock behaviour 83 * is handled differently to create the count down. 84 * \ingroup modes 85 */ 86 87 class World : public WorldStatus 88 { 89 public: 90 typedef std::vector<std::shared_ptr<AbstractKart> > KartList; 91 private: 92 /** A pointer to the global world object for a race. */ 93 static World *m_world[PT_COUNT]; 94 // ------------------------------------------------------------------------ 95 void setAITeam(); 96 // ------------------------------------------------------------------------ 97 std::shared_ptr<AbstractKart> createKartWithTeam 98 (const std::string &kart_ident, int index, int local_player_id, 99 int global_player_id, RaceManager::KartType type, 100 HandicapLevel handicap); 101 102 protected: 103 104 #ifdef DEBUG 105 unsigned int m_magic_number; 106 #endif 107 108 /* Team related variables. */ 109 int m_red_ai; 110 int m_blue_ai; 111 std::map<int, KartTeam> m_kart_team_map; 112 std::map<int, unsigned int> m_kart_position_map; 113 114 /** The list of all karts. */ 115 KartList m_karts; 116 RandomGenerator m_random; 117 118 AbstractKart* m_fastest_kart; 119 /** Number of eliminated karts. */ 120 int m_eliminated_karts; 121 /** Number of eliminated players. */ 122 int m_eliminated_players; 123 /** OVerall number of players. */ 124 int m_num_players; 125 126 bool m_faster_music_active; // true if faster music was activated 127 128 bool m_stop_music_when_dialog_open; 129 130 bool m_unfair_team; 131 132 /** Whether highscores should be used for this kind of race. 133 * True by default, change to false in a child class to disable. 134 */ 135 bool m_use_highscores; 136 137 void updateHighscores (int* best_highscore_rank); 138 void resetAllKarts (); 139 Controller* 140 loadAIController (AbstractKart *kart); 141 142 virtual std::shared_ptr<AbstractKart> createKart 143 (const std::string &kart_ident, int index, int local_player_id, 144 int global_player_id, RaceManager::KartType type, 145 HandicapLevel handicap); 146 147 /** Pointer to the race GUI. The race GUI is handled by world. */ 148 RaceGUIBase *m_race_gui; 149 150 /** The actual race gui needs to be saved when the race result gui is 151 displayed since it is still needed in case of a restart, and it 152 can't simply be created again (since it assumes that it can render 153 to texture without having any scene nodes, but in case of a restart 154 there are scene nodes). */ 155 RaceGUIBase *m_saved_race_gui; 156 157 /** Pausing/unpausing are not done immediately, but at next udpdate. The 158 * use of this is when switching between screens : if we leave a screen 159 * that paused the game, only to go to another screen that pauses back 160 * the game, this mechanism prevents the game from moving on between 161 * the switch. */ 162 bool m_schedule_pause; 163 164 /** Pausing/unpausing are not done immediately, but at next udpdate. The 165 * use of this is when switching between screens : if we leave a screen 166 * that paused the game, only to go to another screen that pauses back 167 * the game, this mechanism prevents the game from moving on between the 168 * switch. */ 169 bool m_schedule_unpause; 170 171 bool m_schedule_exit_race; 172 173 bool m_schedule_tutorial; 174 175 Phase m_scheduled_pause_phase; 176 177 /** Set when the world needs to be deleted but you can't do it immediately 178 * because you are e.g. within World::update() 179 */ 180 bool m_self_destruct; 181 182 /** Set when the world is online and counts network players. */ 183 bool m_is_network_world; 184 185 bool m_ended_early; 186 187 virtual void onGo() OVERRIDE; 188 /** Returns true if the race is over. Must be defined by all modes. */ 189 virtual bool isRaceOver() = 0; 190 virtual void update(int ticks) OVERRIDE; 191 virtual void createRaceGUI(); 192 void updateTrack(int ticks); 193 // ------------------------------------------------------------------------ 194 /** Used for AI karts that are still racing when all player kart finished. 195 * Generally it should estimate the arrival time for those karts, but as 196 * a default (useful for battle mode and ftl races) we just use the 197 * current time for this (since this is a good value for karts still 198 * around at the end of a race, and other criteria (number of lives, 199 * race position) will be used to determine the final order. 200 */ estimateFinishTimeForKart(AbstractKart * kart)201 virtual float estimateFinishTimeForKart(AbstractKart* kart) 202 {return getTime(); } 203 void updateAchievementDataEndRace(); 204 void updateAchievementModeCounters(bool start); 205 206 public: 207 World(); 208 virtual ~World(); 209 // Static functions to access world: 210 // ================================= 211 // ------------------------------------------------------------------------ 212 /** Returns a pointer to the (singleton) world object. */ getWorld()213 static World* getWorld() 214 { 215 ProcessType type = STKProcess::getType(); 216 return m_world[type]; 217 } 218 // ------------------------------------------------------------------------ 219 /** Delete the )singleton) world object, if it exists, and sets the 220 * singleton pointer to NULL. It's harmless to call this if the world 221 * has been deleted already. */ deleteWorld()222 static void deleteWorld() 223 { 224 ProcessType type = STKProcess::getType(); 225 delete m_world[type]; 226 m_world[type] = NULL; 227 } 228 // ------------------------------------------------------------------------ 229 /** Sets the pointer to the world object. This is only used by 230 * the race_manager.*/ setWorld(World * world)231 static void setWorld(World *world) 232 { 233 ProcessType type = STKProcess::getType(); 234 m_world[type] = world; 235 } 236 // ------------------------------------------------------------------------ clear()237 static void clear() { memset(m_world, 0, sizeof(m_world)); } 238 // ------------------------------------------------------------------------ 239 240 // Pure virtual functions 241 // ====================== 242 243 /** Each game mode should have a unique identifier. Override 244 * this method in child classes to provide it. */ 245 virtual const std::string& getIdent() const = 0; 246 // ------------------------------------------------------------------------ 247 /** Returns the number of rescue positions on a given track and game 248 * mode. */ 249 virtual unsigned int getNumberOfRescuePositions() const; 250 // ------------------------------------------------------------------------ 251 /** Determines the rescue position index of the specified kart. */ 252 virtual unsigned int getRescuePositionIndex(AbstractKart *kart) = 0; 253 // ------------------------------------------------------------------------ 254 /** Returns the bullet transformation for the specified rescue index. */ 255 virtual btTransform getRescueTransform(unsigned int index) const; 256 // ------------------------------------------------------------------------ 257 virtual void moveKartAfterRescue(AbstractKart* kart); 258 // ------------------------------------------------------------------------ 259 /** Called when it is needed to know whether this kind of race involves 260 * counting laps. */ 261 virtual bool raceHasLaps() = 0; 262 // ------------------------------------------------------------------------ 263 /** Returns the number of laps for a given kart. Only valid when 264 * raceHasLaps() - otherwise STK will abort. */ getFinishedLapsOfKart(unsigned int kart_index) const265 virtual int getFinishedLapsOfKart(unsigned int kart_index) const 266 { 267 assert(false); return -1; // remove compiler warning 268 } // getFinishedLapsOfKart 269 // ------------------------------------------------------------------------ 270 /** Called by the code that draws the list of karts on the race GUI 271 * to know what needs to be drawn in the current mode. */ 272 virtual void getKartsDisplayInfo( 273 std::vector<RaceGUIBase::KartIconDisplayInfo> *info)= 0; 274 // ------------------------------------------------------------------------ 275 276 // Virtual functions 277 // ================= 278 virtual void init(); 279 virtual void updateGraphics(float dt); 280 virtual void terminateRace() OVERRIDE; 281 virtual void reset(bool restart=false) OVERRIDE; 282 virtual void pause(Phase phase) OVERRIDE; 283 virtual void unpause() OVERRIDE; 284 virtual void getDefaultCollectibles(int *collectible_type, 285 int *amount ); 286 // ------------------------------------------------------------------------ 287 /** Receives notification if an item is collected. Used for easter eggs. */ collectedItem(const AbstractKart * kart,const ItemState * item)288 virtual void collectedItem(const AbstractKart *kart, 289 const ItemState *item ) {} 290 // ------------------------------------------------------------------------ endRaceEarly()291 virtual void endRaceEarly() { return; } 292 // ------------------------------------------------------------------------ hasRaceEndedEarly() const293 virtual bool hasRaceEndedEarly() const { return m_ended_early; } 294 // ------------------------------------------------------------------------ 295 /** Called to determine whether this race mode uses bonus boxes. */ haveBonusBoxes()296 virtual bool haveBonusBoxes() { return true; } 297 // ------------------------------------------------------------------------ 298 /** Returns if this mode should use fast music (if available). */ useFastMusicNearEnd() const299 virtual bool useFastMusicNearEnd() const { return true; } 300 // ------------------------------------------------------------------------ 301 /** If you want to do something to karts or their graphics at the start 302 * of the race, override this. */ kartAdded(AbstractKart * kart,scene::ISceneNode * node)303 virtual void kartAdded(AbstractKart* kart, scene::ISceneNode* node) {} 304 // ------------------------------------------------------------------------ 305 /** Called whenever a kart starts a new lap. Meaningless (and won't be 306 * called) in non-laped races. 307 */ newLap(unsigned int kart_index)308 virtual void newLap(unsigned int kart_index) {} 309 // ------------------------------------------------------------------------ 310 /** Called when a kart was hit by a projectile. */ kartHit(int kart_id,int hitter=-1)311 virtual bool kartHit(int kart_id, int hitter = -1) { return false; } 312 // ------------------------------------------------------------------------ onMouseClick(int x,int y)313 virtual void onMouseClick(int x, int y) {}; 314 315 // Other functions 316 // =============== 317 Highscores *getHighscores() const; 318 void schedulePause(Phase phase); 319 void scheduleUnpause(); scheduleExitRace()320 void scheduleExitRace() { m_schedule_exit_race = true; } 321 void scheduleTutorial(); 322 void updateWorld(int ticks); 323 void handleExplosion(const Vec3 &xyz, AbstractKart *kart_hit, 324 PhysicalObject *object); 325 AbstractKart* getPlayerKart(unsigned int player) const; 326 AbstractKart* getLocalPlayerKart(unsigned int n) const; 327 virtual const btTransform &getStartTransform(int index); 328 void moveKartTo(AbstractKart* kart, const btTransform &t); 329 // ------------------------------------------------------------------------ 330 /** Returns a pointer to the race gui. */ getRaceGUI() const331 RaceGUIBase *getRaceGUI() const { return m_race_gui;} 332 // ------------------------------------------------------------------------ 333 /** Returns the number of karts in the race. */ getNumKarts() const334 unsigned int getNumKarts() const { return (unsigned int) m_karts.size(); } 335 // ------------------------------------------------------------------------ 336 /** Returns the kart with a given world id. */ getKart(int kartId) const337 AbstractKart *getKart(int kartId) const { 338 assert(kartId >= 0 && kartId < int(m_karts.size())); 339 return m_karts[kartId].get(); } 340 // ------------------------------------------------------------------------ 341 /** Returns all karts. */ getKarts() const342 const KartList & getKarts() const { return m_karts; } 343 // ------------------------------------------------------------------------ 344 /** Returns the number of currently active (i.e.non-elikminated) karts. */ getCurrentNumKarts() const345 unsigned int getCurrentNumKarts() const { return (int)m_karts.size() - 346 m_eliminated_karts; } 347 // ------------------------------------------------------------------------ 348 /** Returns the number of currently active (i.e. non-eliminated) players.*/ getCurrentNumPlayers() const349 unsigned int getCurrentNumPlayers() const { return m_num_players - 350 m_eliminated_players;} 351 // ------------------------------------------------------------------------ resetElimination()352 void resetElimination() 353 { 354 m_eliminated_karts = 0; 355 m_eliminated_players = 0; 356 } 357 // ------------------------------------------------------------------------ addReservedKart(int kart_id)358 virtual void addReservedKart(int kart_id) 359 { 360 if (m_eliminated_karts > 0) 361 m_eliminated_karts--; 362 } 363 // ------------------------------------------------------------------------ saveCompleteState(BareNetworkString * bns,STKPeer * peer)364 virtual void saveCompleteState(BareNetworkString* bns, STKPeer* peer) {} 365 // ------------------------------------------------------------------------ restoreCompleteState(const BareNetworkString & buffer)366 virtual void restoreCompleteState(const BareNetworkString& buffer) {} 367 // ------------------------------------------------------------------------ 368 /** The code that draws the timer should call this first to know 369 * whether the game mode wants a timer drawn. */ shouldDrawTimer() const370 virtual bool shouldDrawTimer() const 371 { return isActiveRacePhase() && getClockMode() != CLOCK_NONE; } 372 // ------------------------------------------------------------------------ 373 /** \return whether this world can generate/have highscores */ useHighScores() const374 bool useHighScores() const { return m_use_highscores; } 375 // ------------------------------------------------------------------------ 376 /** Override if you want to know when a kart presses fire */ onFirePressed(Controller * who)377 virtual void onFirePressed(Controller* who) {} 378 // ------------------------------------------------------------------------ 379 /** Whether to compute checkline requirements for each world on the 380 * quadgraph. Override to change value. */ useChecklineRequirements() const381 virtual bool useChecklineRequirements() const { return false; } 382 // ------------------------------------------------------------------------ 383 virtual void escapePressed(); 384 // ------------------------------------------------------------------------ loadCustomModels()385 virtual void loadCustomModels() {} 386 // ------------------------------------------------------------------------ 387 void eliminateKart(int kart_number, bool notify_of_elimination = true); 388 // ------------------------------------------------------------------------ setUnfairTeam(bool val)389 void setUnfairTeam(bool val) { m_unfair_team = val; } 390 // ------------------------------------------------------------------------ hasTeam() const391 virtual bool hasTeam() const { return false; } 392 // ------------------------------------------------------------------------ 393 /** Get the team of kart in world (including AIs) */ 394 KartTeam getKartTeam(unsigned int kart_id) const; 395 // ------------------------------------------------------------------------ 396 int getTeamNum(KartTeam team) const; 397 // ------------------------------------------------------------------------ 398 /** Set the network mode (true if networked) */ setNetworkWorld(bool is_networked)399 void setNetworkWorld(bool is_networked) { m_is_network_world = is_networked; } 400 // ------------------------------------------------------------------------ isNetworkWorld() const401 bool isNetworkWorld() const { return m_is_network_world; } 402 // ------------------------------------------------------------------------ 403 /** Set the team arrow on karts if necessary*/ 404 void initTeamArrows(AbstractKart* k); 405 // ------------------------------------------------------------------------ 406 /** Used by server to get the current started game progress in either or 407 * both remaining time or progress in percent. uint32_t max for either or 408 * both if not available. */ getGameStartedProgress() const409 virtual std::pair<uint32_t, uint32_t> getGameStartedProgress() const 410 { 411 return std::make_pair(std::numeric_limits<uint32_t>::max(), 412 std::numeric_limits<uint32_t>::max()); 413 } 414 // ------------------------------------------------------------------------ isGoalPhase() const415 virtual bool isGoalPhase() const { return false; } 416 }; // World 417 418 #endif 419 420 /* EOF */ 421