Only pause game on focus lose when game session is active
[supertux.git] / src / supertux / game_session.cpp
index 88f7704..d29300d 100644 (file)
@@ -20,7 +20,7 @@
 #include <fstream>
 
 #include "audio/sound_manager.hpp"
-#include "control/joystickkeyboardcontroller.hpp"
+#include "control/input_manager.hpp"
 #include "gui/menu.hpp"
 #include "gui/menu_manager.hpp"
 #include "math/random_generator.hpp"
 #include "object/endsequence_walkright.hpp"
 #include "object/level_time.hpp"
 #include "object/player.hpp"
+#include "scripting/scripting.hpp"
+#include "scripting/squirrel_util.hpp"
 #include "scripting/squirrel_util.hpp"
 #include "supertux/gameconfig.hpp"
-#include "supertux/levelintro.hpp"
 #include "supertux/globals.hpp"
-#include "supertux/screen_manager.hpp"
+#include "supertux/levelintro.hpp"
+#include "supertux/levelset_screen.hpp"
 #include "supertux/menu/menu_storage.hpp"
-#include "supertux/menu/game_menu.hpp"
 #include "supertux/menu/options_menu.hpp"
+#include "supertux/player_status.hpp"
+#include "supertux/savegame.hpp"
+#include "supertux/screen_fade.hpp"
+#include "supertux/screen_manager.hpp"
 #include "supertux/sector.hpp"
 #include "util/file_system.hpp"
 #include "util/gettext.hpp"
 #include "worldmap/worldmap.hpp"
 
-GameSession::GameSession(const std::string& levelfile_, PlayerStatus* player_status, Statistics* statistics) :
-  level(0), 
-  statistics_backdrop(),
+GameSession::GameSession(const std::string& levelfile_, Savegame& savegame, Statistics* statistics) :
+  level(),
+  statistics_backdrop(Surface::create("images/engine/menu/score-backdrop.png")),
   scripts(),
-  currentsector(0),
+  currentsector(nullptr),
   levelnb(),
   pause_menu_frame(),
   end_sequence(0),
-  game_pause(),
-  speed_before_pause(),
-  levelfile(levelfile_), 
+  game_pause(false),
+  speed_before_pause(ScreenManager::current()->get_speed()),
+  levelfile(levelfile_),
   reset_sector(),
   reset_pos(),
   newsector(),
   newspawnpoint(),
   best_level_statistics(statistics),
-  player_status(player_status),
-  capture_demo_stream(0), 
+  m_savegame(savegame),
+  capture_demo_stream(0),
   capture_file(),
-  playback_demo_stream(0), 
+  playback_demo_stream(0),
   demo_controller(0),
-  game_menu(),
-  play_time(0), 
-  edit_mode(false), 
-  levelintro_shown(false)
+  play_time(0),
+  edit_mode(false),
+  levelintro_shown(false),
+  coins_at_start(),
+  bonus_at_start(),
+  max_fire_bullets_at_start(),
+  max_ice_bullets_at_start(),
+  active(false)
 {
-  currentsector = NULL;
-
-  game_pause = false;
-  speed_before_pause = g_screen_manager->get_speed();
-
-  statistics_backdrop = Surface::create("images/engine/menu/score-backdrop.png");
-
-  restart_level();
-
-  game_menu.reset(new GameMenu(*level));
+  if (restart_level() != 0)
+    throw std::runtime_error ("Initializing the level failed.");
 }
 
-void
-GameSession::restart_level()
+int
+GameSession::restart_level(bool after_death)
 {
+    PlayerStatus* currentStatus = m_savegame.get_player_status();
+    coins_at_start = currentStatus->coins;
+    bonus_at_start = currentStatus->bonus;
+    max_fire_bullets_at_start = currentStatus->max_fire_bullets;
+    max_ice_bullets_at_start = currentStatus->max_ice_bullets;
 
   if (edit_mode) {
     force_ghost_mode();
-    return;
+    return (-1);
   }
 
   game_pause   = false;
   end_sequence = 0;
 
-  g_main_controller->reset();
+  InputManager::current()->reset();
 
   currentsector = 0;
 
@@ -112,7 +118,6 @@ GameSession::restart_level()
         msg << "Couldn't find sector '" << reset_sector << "' for resetting tux.";
         throw std::runtime_error(msg.str());
       }
-      level->stats.declare_invalid();
       currentsector->activate(reset_pos);
     } else {
       currentsector = level->get_sector("main");
@@ -123,11 +128,16 @@ GameSession::restart_level()
     }
   } catch(std::exception& e) {
     log_fatal << "Couldn't start level: " << e.what() << std::endl;
-    g_screen_manager->exit_screen();
+    ScreenManager::current()->pop_screen();
+    return (-1);
+  }
+  if(after_death == true) {
+    currentsector->resume_music();
+  }
+  else {
+    SoundManager::current()->stop_music();
+    currentsector->play_music(LEVEL_MUSIC);
   }
-
-  sound_manager->stop_music();
-  currentsector->play_music(LEVEL_MUSIC);
 
   if(capture_file != "") {
     int newSeed=0;               // next run uses a new seed
@@ -137,6 +147,8 @@ GameSession::restart_level()
     log_info << "Next run uses random seed " << g_config->random_seed <<std::endl;
     record_demo(capture_file);
   }
+
+  return (0);
 }
 
 GameSession::~GameSession()
@@ -181,6 +193,8 @@ GameSession::get_demo_random_seed(const std::string& filename)
     else
       log_info << "Demo file contains no random number" << std::endl;
   }
+  delete test_stream;
+  test_stream = nullptr;
   return 0;
 }
 
@@ -235,11 +249,12 @@ void
 GameSession::toggle_pause()
 {
   // pause
-  if(!game_pause) {
-    speed_before_pause = g_screen_manager->get_speed();
-    g_screen_manager->set_speed(0);
-    MenuManager::set_current(game_menu.get());
-    game_menu->set_active_item(MNID_CONTINUE);
+  if (!game_pause && !MenuManager::instance().is_active())
+  {
+    speed_before_pause = ScreenManager::current()->get_speed();
+    ScreenManager::current()->set_speed(0);
+    MenuManager::instance().set_menu(MenuStorage::GAME_MENU);
+    SoundManager::current()->pause_music();
     game_pause = true;
   }
 
@@ -247,14 +262,32 @@ GameSession::toggle_pause()
 }
 
 void
-GameSession::set_editmode(bool edit_mode)
+GameSession::abort_level()
+{
+  MenuManager::instance().clear_menu_stack();
+  ScreenManager::current()->pop_screen();
+  currentsector->player->set_bonus(bonus_at_start);
+  PlayerStatus *currentStatus = m_savegame.get_player_status();
+  currentStatus->coins = coins_at_start;
+  currentStatus->max_fire_bullets = max_fire_bullets_at_start;
+  currentStatus->max_ice_bullets = max_ice_bullets_at_start;
+}
+
+bool
+GameSession::is_active() const
+{
+  return !game_pause && active;
+}
+
+void
+GameSession::set_editmode(bool edit_mode_)
 {
-  if (this->edit_mode == edit_mode) return;
-  this->edit_mode = edit_mode;
+  if (this->edit_mode == edit_mode_) return;
+  this->edit_mode = edit_mode_;
 
-  currentsector->get_players()[0]->set_edit_mode(edit_mode);
+  currentsector->get_players()[0]->set_edit_mode(edit_mode_);
 
-  if (edit_mode) {
+  if (edit_mode_) {
 
     // entering edit mode
 
@@ -305,16 +338,6 @@ GameSession::run_script(std::istream& in, const std::string& sourcename)
 void
 GameSession::process_events()
 {
-  // end of pause mode?
-  // XXX this looks like a fail-safe to unpause the game if there's no menu
-  // XXX having it enabled causes some unexpected problems
-  // XXX hopefully disabling it won't...
-  /*
-    if(!Menu::current() && game_pause) {
-    game_pause = false;
-    }
-  */
-
   // playback a demo?
   if(playback_demo_stream != 0) {
     demo_controller->update();
@@ -340,12 +363,13 @@ GameSession::process_events()
 
   // save input for demo?
   if(capture_demo_stream != 0) {
-    capture_demo_stream ->put(g_main_controller->hold(Controller::LEFT));
-    capture_demo_stream ->put(g_main_controller->hold(Controller::RIGHT));
-    capture_demo_stream ->put(g_main_controller->hold(Controller::UP));
-    capture_demo_stream ->put(g_main_controller->hold(Controller::DOWN));
-    capture_demo_stream ->put(g_main_controller->hold(Controller::JUMP));
-    capture_demo_stream ->put(g_main_controller->hold(Controller::ACTION));
+    Controller *controller = InputManager::current()->get_controller();
+    capture_demo_stream ->put(controller->hold(Controller::LEFT));
+    capture_demo_stream ->put(controller->hold(Controller::RIGHT));
+    capture_demo_stream ->put(controller->hold(Controller::UP));
+    capture_demo_stream ->put(controller->hold(Controller::DOWN));
+    capture_demo_stream ->put(controller->hold(Controller::JUMP));
+    capture_demo_stream ->put(controller->hold(Controller::ACTION));
   }
 }
 
@@ -358,7 +382,7 @@ GameSession::check_end_conditions()
   if(end_sequence && end_sequence->is_done()) {
     finish(true);
   } else if (!end_sequence && tux->is_dead()) {
-    restart_level();
+    restart_level(true);
   }
 }
 
@@ -381,57 +405,60 @@ GameSession::draw_pause(DrawingContext& context)
 }
 
 void
-GameSession::process_menu()
-{
-  Menu* menu = MenuManager::current();
-  if(menu) {
-    if(menu == game_menu.get()) {
-      switch (game_menu->check()) {
-        case MNID_CONTINUE:
-          MenuManager::set_current(0);
-          toggle_pause();
-          break;
-        case MNID_ABORTLEVEL:
-          MenuManager::set_current(0);
-          g_screen_manager->exit_screen();
-          break;
-      }
-    }
-  }
-}
-
-void
 GameSession::setup()
 {
+  if (currentsector == NULL)
+    return;
+
   if(currentsector != Sector::current()) {
     currentsector->activate(currentsector->player->get_pos());
   }
   currentsector->play_music(LEVEL_MUSIC);
 
-  // Eat unneeded events
-  SDL_Event event;
-  while(SDL_PollEvent(&event))
-  {}
-
-  if (!levelintro_shown) {
+  int total_stats_to_be_collected = level->stats.total_coins + level->stats.total_badguys + level->stats.total_secrets;
+  if ((!levelintro_shown) && (total_stats_to_be_collected > 0)) {
     levelintro_shown = true;
-    g_screen_manager->push_screen(new LevelIntro(level.get(), best_level_statistics));
+    active = false;
+    ScreenManager::current()->push_screen(std::unique_ptr<Screen>(new LevelIntro(level.get(), best_level_statistics)));
   }
 }
 
 void
+GameSession::leave()
+{
+}
+
+void
 GameSession::update(float elapsed_time)
 {
+  // Set active flag
+  if(!active)
+  {
+    active = true;
+  }
   // handle controller
-  if(g_main_controller->pressed(Controller::PAUSE_MENU))
+  if(InputManager::current()->get_controller()->pressed(Controller::ESCAPE) ||
+     InputManager::current()->get_controller()->pressed(Controller::START))
+  {
     on_escape_press();
+  }
+
+  if(InputManager::current()->get_controller()->pressed(Controller::CHEAT_MENU) &&
+     g_config->developer_mode)
+  {
+    if (!MenuManager::instance().is_active())
+    {
+      game_pause = true;
+      MenuManager::instance().set_menu(MenuStorage::CHEAT_MENU);
+    }
+  }
 
   process_events();
-  process_menu();
 
   // Unpause the game if the menu has been closed
-  if (game_pause && !MenuManager::current()) {
-    g_screen_manager->set_speed(speed_before_pause);
+  if (game_pause && !MenuManager::instance().is_active()) {
+    ScreenManager::current()->set_speed(speed_before_pause);
+    SoundManager::current()->resume_music();
     game_pause = false;
   }
 
@@ -470,8 +497,11 @@ GameSession::update(float elapsed_time)
     }
   }
 
+  if(currentsector == NULL)
+    return;
+  
   // update sounds
-  if (currentsector && currentsector->camera) sound_manager->set_listener_position(currentsector->camera->get_center());
+  if (currentsector->camera) SoundManager::current()->set_listener_position(currentsector->camera->get_center());
 
   /* Handle music: */
   if (end_sequence)
@@ -501,10 +531,17 @@ GameSession::finish(bool win)
 
   if(win) {
     if(WorldMap::current())
+    {
       WorldMap::current()->finished_level(level.get());
+    }
+
+    if (LevelsetScreen::current())
+    {
+      LevelsetScreen::current()->finished_level(win);
+    }
   }
 
-  g_screen_manager->exit_screen();
+  ScreenManager::current()->pop_screen();
 }
 
 void
@@ -552,33 +589,33 @@ GameSession::start_sequence(const std::string& sequencename)
 
   if (sequencename == "endsequence") {
     if (currentsector->get_players()[0]->get_physic().get_velocity_x() < 0) {
-      end_sequence = new EndSequenceWalkLeft();
+      end_sequence = std::make_shared<EndSequenceWalkLeft>();
     } else {
-      end_sequence = new EndSequenceWalkRight();
+      end_sequence = std::make_shared<EndSequenceWalkRight>();
     }
   } else if (sequencename == "fireworks") {
-    end_sequence = new EndSequenceFireworks();
+    end_sequence = std::make_shared<EndSequenceFireworks>();
   } else {
     log_warning << "Unknown sequence '" << sequencename << "'. Ignoring." << std::endl;
     return;
   }
 
   /* slow down the game for end-sequence */
-  g_screen_manager->set_speed(0.5f);
+  ScreenManager::current()->set_speed(0.5f);
 
   currentsector->add_object(end_sequence);
   end_sequence->start();
 
-  sound_manager->play_music("music/leveldone.ogg", false);
-  currentsector->player->invincible_timer.start(10000.0f);
+  SoundManager::current()->play_music("music/leveldone.ogg", false);
+  currentsector->player->set_winning();
 
   // Stop all clocks.
-  for(std::vector<GameObject*>::iterator i = currentsector->gameobjects.begin();
+  for(auto i = currentsector->gameobjects.begin();
       i != currentsector->gameobjects.end(); ++i)
   {
-    GameObject* obj = *i;
+    GameObjectPtr obj = *i;
 
-    LevelTime* lt = dynamic_cast<LevelTime*> (obj);
+    auto lt = std::dynamic_pointer_cast<LevelTime>(obj);
     if(lt)
       lt->stop();
   }
@@ -588,7 +625,7 @@ GameSession::start_sequence(const std::string& sequencename)
 void
 GameSession::drawstatus(DrawingContext& context)
 {
-  player_status->draw(context);
+  m_savegame.get_player_status()->draw(context);
 
   // draw level stats while end_sequence is running
   if (end_sequence) {