LEVEL_RESULT playsingle_controller::play_scenario( const config::const_child_itors &story, bool skip_replay) { uint32_t start = SDL_GetTicks(); // level_ // save game: [snapshort] in save file // new game: [scenario] in <scenarios>.cfg // Start music. BOOST_FOREACH (const config &m, level_.child_range("music")) { sound::play_music_config(m); } sound::commit_music_changes(); if(!skip_replay) { // show_story(*gui_, level_["name"], story); // gui2::show_story(*gui_, level_["name"], story); } gui_->labels().read(level_); // Read sound sources assert(soundsources_manager_ != NULL); BOOST_FOREACH (const config &s, level_.child_range("sound_source")) { soundsource::sourcespec spec(s); soundsources_manager_->add(spec); } uint32_t end_sound_sources = SDL_GetTicks(); posix_print("playsingle_controller::play_scenario, sound sources, used time: %u ms\n", end_sound_sources - start); set_victory_when_enemy_no_city(level_["victory_when_enemy_no_city"].to_bool(true)); end_level_data &end_level = get_end_level_data(); end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage); end_level.carryover_add = level_["carryover_add"].to_bool(); try { uint32_t end_entering_try = SDL_GetTicks(); posix_print("playsingle_controller::play_scenario, entering try, used time: %u ms\n", end_entering_try - end_sound_sources); fire_prestart(!loading_game_); uint32_t end_fire_prestart = SDL_GetTicks(); posix_print("playsingle_controller::play_scenario, fire_prestrt, used time: %u ms\n", end_fire_prestart - end_entering_try); init_gui(); fire_start(!loading_game_); gui_->recalculate_minimap(); // replaying_ = (recorder.at_end() == false); // Initialize countdown clock. std::vector<team>::iterator t; for(t = teams_.begin(); t != teams_.end(); ++t) { if (gamestate_.mp_settings().mp_countdown && !loading_game_ ){ t->set_countdown_time(1000 * gamestate_.mp_settings().mp_countdown_init_time); } } // if we loaded a save file in linger mode, skip to it. if (linger_) { //determine the bonus gold handling for this scenario const config end_cfg = level_.child_or_empty("endlevel"); end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage); end_level.carryover_add = level_["carr`yover_add"].to_bool(); end_level.gold_bonus = end_cfg["bonus"].to_bool(true); end_level.carryover_report = false; throw end_level_exception(SKIP_TO_LINGER); } // Avoid autosaving after loading, but still // allow the first turn to have an autosave. bool save = !loading_game_; for(; ; first_player_ = 1) { play_turn(save); save = true; } //end for loop } catch(game::load_game_exception& lge) { // Loading a new game is effectively a quit. // if (lge.game != "") { gamestate_ = game_state(); } throw lge; } catch (end_level_exception &end_level_exn) { LEVEL_RESULT end_level_result = end_level_exn.result; if (!end_level.custom_endlevel_music.empty()) { if (end_level_result == DEFEAT) { set_defeat_music_list(end_level.custom_endlevel_music); } else { set_victory_music_list(end_level.custom_endlevel_music); } } if (teams_.empty()) { //store persistent teams gamestate_.snapshot = config(); return VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event } const bool obs = is_observer(); if (end_level_result == DEFEAT || end_level_result == VICTORY) { gamestate_.classification().completion = (end_level_exn.result == VICTORY) ? "victory" : "defeat"; // If we're a player, and the result is victory/defeat, then send // a message to notify the server of the reason for the game ending. if (!obs) { config cfg; config& info = cfg.add_child("info"); info["type"] = "termination"; info["condition"] = "game over"; info["result"] = gamestate_.classification().completion; network::send_data(cfg, 0); } else { gui2::show_transient_message(gui_->video(),_("Game Over"), _("The game is over.")); return OBSERVER_END; } } if (end_level_result == QUIT) { return QUIT; } else if (end_level_result == DEFEAT) { gamestate_.classification().completion = "defeat"; game_events::fire("defeat"); if (!obs) { const std::string& defeat_music = select_defeat_music(); if(defeat_music.empty() != true) sound::play_music_once(defeat_music); return DEFEAT; } else { return QUIT; } } else if (end_level_result == VICTORY) { gamestate_.classification().completion = !end_level.linger_mode ? "running" : "victory"; game_events::fire("victory"); // // Play victory music once all victory events // are finished, if we aren't observers. // // Some scenario authors may use 'continue' // result for something that is not story-wise // a victory, so let them use [music] tags // instead should they want special music. // if (!obs && end_level.linger_mode) { const std::string& victory_music = select_victory_music(); if(victory_music.empty() != true) sound::play_music_once(victory_music); } // Add all the units that survived the scenario. LOG_NG << "Add units that survived the scenario to the recall list.\n"; //store all units that survived (recall list for the next scenario) in snapshot gamestate_.snapshot = config(); //store gold and report victory store_gold(obs); return VICTORY; } else if (end_level_result == SKIP_TO_LINGER) { LOG_NG << "resuming from loaded linger state...\n"; //as carryover information is stored in the snapshot, we have to re-store it after loading a linger state gamestate_.snapshot = config(); store_gold(); return VICTORY; } } // end catch catch(network::error& e) { bool disconnect = false; if(e.socket) { e.disconnect(); disconnect = true; } config snapshot; to_config(snapshot); savegame::game_savegame save(heros_, heros_start_, gamestate_, *gui_, snapshot); save.save_game_interactive(gui_->video(), _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), gui::YES_NO); if(disconnect) { throw network::error(); } else { return QUIT; } } return QUIT; }
LEVEL_RESULT playsingle_controller::play_scenario(const config& level) { LOG_NG << "in playsingle_controller::play_scenario()...\n"; // Start music. BOOST_FOREACH(const config &m, level.child_range("music")) { sound::play_music_config(m); } sound::commit_music_changes(); if(!this->is_skipping_replay()) { show_story(gui_->video(), get_scenario_name(), level.child_range("story")); } gui_->labels().read(level); // Read sound sources assert(soundsources_manager_ != NULL); BOOST_FOREACH(const config &s, level.child_range("sound_source")) { try { soundsource::sourcespec spec(s); soundsources_manager_->add(spec); } catch (bad_lexical_cast &) { ERR_NG << "Error when parsing sound_source config: bad lexical cast." << std::endl; ERR_NG << "sound_source config was: " << s.debug() << std::endl; ERR_NG << "Skipping this sound source..." << std::endl; } } LOG_NG << "entering try... " << (SDL_GetTicks() - ticks()) << "\n"; try { play_scenario_init(); // clears level config; this->saved_game_.remove_snapshot(); if (!is_regular_game_end() && !linger_) { play_scenario_main_loop(); } if (game_config::exit_at_end) { exit(0); } const bool is_victory = get_end_level_data_const().is_victory; if(gamestate().gamedata_.phase() <= game_data::PRESTART) { sdl::draw_solid_tinted_rectangle( 0, 0, gui_->video().getx(), gui_->video().gety(), 0, 0, 0, 1.0, gui_->video().getSurface() ); update_rect(0, 0, gui_->video().getx(), gui_->video().gety()); } ai_testing::log_game_end(); const end_level_data& end_level = get_end_level_data_const(); if (!end_level.transient.custom_endlevel_music.empty()) { if (!is_victory) { set_defeat_music_list(end_level.transient.custom_endlevel_music); } else { set_victory_music_list(end_level.transient.custom_endlevel_music); } } if (gamestate().board_.teams().empty()) { //store persistent teams saved_game_.set_snapshot(config()); return LEVEL_RESULT::VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event } if(linger_) { LOG_NG << "resuming from loaded linger state...\n"; //as carryover information is stored in the snapshot, we have to re-store it after loading a linger state saved_game_.set_snapshot(config()); if(!is_observer()) { persist_.end_transaction(); } return LEVEL_RESULT::VICTORY; } pump().fire(is_victory ? "victory" : "defeat"); { // Block for set_scontext_synced_base set_scontext_synced_base sync; pump().fire("scenario end"); } if(end_level.proceed_to_next_level) { gamestate().board_.heal_all_survivors(); } if(is_observer()) { gui2::show_transient_message(gui_->video(), _("Game Over"), _("The game is over.")); return LEVEL_RESULT::OBSERVER_END; } // If we're a player, and the result is victory/defeat, then send // a message to notify the server of the reason for the game ending. network::send_data(config_of ("info", config_of ("type", "termination") ("condition", "game over") ("result", is_victory ? "victory" : "defeat") )); // Play victory music once all victory events // are finished, if we aren't observers. // // Some scenario authors may use 'continue' // result for something that is not story-wise // a victory, so let them use [music] tags // instead should they want special music. const std::string& end_music = is_victory ? select_victory_music() : select_defeat_music(); if(end_music.empty() != true) { sound::play_music_once(end_music); } persist_.end_transaction(); return is_victory ? LEVEL_RESULT::VICTORY : LEVEL_RESULT::DEFEAT; } catch(const game::load_game_exception &) { // Loading a new game is effectively a quit. // if ( game::load_game_exception::game != "" ) { saved_game_ = saved_game(); } throw; } catch(network::error& e) { bool disconnect = false; if(e.socket) { e.disconnect(); disconnect = true; } scoped_savegame_snapshot snapshot(*this); savegame::ingame_savegame save(saved_game_, *gui_, preferences::save_compression_format()); save.save_game_interactive(gui_->video(), _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), gui::YES_NO); if(disconnect) { throw network::error(); } else { return LEVEL_RESULT::QUIT; } } return LEVEL_RESULT::QUIT; }
play_controller::play_controller(const config& level, game_state& state_of_game, const int ticks, const int num_turns, const config& game_config, CVideo& video, bool skip_replay) : controller_base(ticks, game_config, video), observer(), savegame_config(), animation_cache(), prefs_disp_manager_(), tooltips_manager_(), events_manager_(), halo_manager_(), labels_manager_(), help_manager_(&game_config), mouse_handler_(NULL, teams_, units_, map_), menu_handler_(NULL, units_, teams_, level, map_, game_config, state_of_game), soundsources_manager_(), tod_manager_(level, num_turns), pathfind_manager_(), persist_(), gui_(), statistics_context_(level["name"]), level_(level), teams_(), gamestate_(state_of_game), gamedata_(level), map_(game_config, level), units_(), undo_stack_(new actions::undo_list(level.child("undo_stack"))), whiteboard_manager_(), xp_mod_(level["experience_modifier"].to_int(100)), loading_game_(level["playing_team"].empty() == false), first_human_team_(-1), player_number_(1), first_player_(level_["playing_team"].to_int() + 1), start_turn_(tod_manager_.turn()), // tod_manager_ constructed above is_host_(true), skip_replay_(skip_replay), linger_(false), it_is_a_new_turn_(true), init_side_done_(level["init_side_done"].to_bool(true)), savenames_(), wml_commands_(), victory_when_enemies_defeated_(true), remove_from_carryover_on_defeat_(true), end_level_data_(), victory_music_(), defeat_music_(), scope_() { resources::controller = this; resources::gamedata = &gamedata_; resources::game_map = &map_; resources::persist = &persist_; resources::state_of_game = &gamestate_; resources::teams = &teams_; resources::tod_manager = &tod_manager_; resources::undo_stack = undo_stack_.get(); resources::units = &units_; persist_.start_transaction(); // Setup victory and defeat music set_victory_music_list(level_["victory_music"]); set_defeat_music_list(level_["defeat_music"]); game_config::add_color_info(level); hotkey::deactivate_all_scopes(); hotkey::set_scope_active(hotkey::SCOPE_GENERAL); hotkey::set_scope_active(hotkey::SCOPE_GAME); try { init(video); } catch (...) { clear_resources(); throw; } }
LEVEL_RESULT playsingle_controller::play_scenario( const config::const_child_itors &story, bool skip_replay) { LOG_NG << "in playsingle_controller::play_scenario()...\n"; // Start music. foreach (const config &m, level_.child_range("music")) { sound::play_music_config(m); } sound::commit_music_changes(); if(!skip_replay) { show_story(*gui_, level_["name"], story); } gui_->labels().read(level_); // Read sound sources assert(soundsources_manager_ != NULL); foreach (const config &s, level_.child_range("sound_source")) { soundsource::sourcespec spec(s); soundsources_manager_->add(spec); } set_victory_when_enemies_defeated(level_["victory_when_enemies_defeated"].to_bool(true)); end_level_data &end_level = get_end_level_data(); end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage); end_level.carryover_add = level_["carryover_add"].to_bool(); bool past_prestart = false; LOG_NG << "entering try... " << (SDL_GetTicks() - ticks_) << "\n"; try { fire_prestart(!loading_game_); init_gui(); past_prestart = true; LOG_NG << "first_time..." << (recorder.is_skipping() ? "skipping" : "no skip") << "\n"; events::raise_draw_event(); fire_start(!loading_game_); gui_->recalculate_minimap(); replaying_ = (recorder.at_end() == false); LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks_) << "\n"; // Initialize countdown clock. std::vector<team>::iterator t; for(t = teams_.begin(); t != teams_.end(); ++t) { if (gamestate_.mp_settings().mp_countdown && !loading_game_ ){ t->set_countdown_time(1000 * gamestate_.mp_settings().mp_countdown_init_time); } } // if we loaded a save file in linger mode, skip to it. if (linger_) { //determine the bonus gold handling for this scenario end_level.read(level_.child_or_empty("endlevel")); end_level.carryover_report = false; end_level.disabled = true; throw end_level_exception(SKIP_TO_LINGER); } // Avoid autosaving after loading, but still // allow the first turn to have an autosave. bool save = !loading_game_; ai_testing::log_game_start(); for(; ; first_player_ = 1) { play_turn(save); save = true; } //end for loop #ifdef _MSC_VER //MSVC claims that const game::load_game_exception& lge would be unreferenced... #pragma warning (push) #pragma warning (disable : 4101) #endif } catch(const game::load_game_exception& lge) { // Loading a new game is effectively a quit. // if (lge.game != "") { gamestate_ = game_state(); } throw; } catch (end_level_exception &end_level_exn) { if(!past_prestart) { draw_solid_tinted_rectangle( 0, 0, gui_->video().getx(), gui_->video().gety(), 0, 0, 0, 1.0, gui_->video().getSurface() ); update_rect(0, 0, gui_->video().getx(), gui_->video().gety()); } ai_testing::log_game_end(); LEVEL_RESULT end_level_result = end_level_exn.result; if (!end_level.custom_endlevel_music.empty()) { if (end_level_result == DEFEAT) { set_defeat_music_list(end_level.custom_endlevel_music); } else { set_victory_music_list(end_level.custom_endlevel_music); } } if (teams_.empty()) { //store persistent teams gamestate_.snapshot = config(); store_recalls(); return VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event } const bool obs = is_observer(); if (game_config::exit_at_end) { exit(0); } if (end_level_result == DEFEAT || end_level_result == VICTORY) { gamestate_.classification().completion = (end_level_exn.result == VICTORY) ? "victory" : "defeat"; // If we're a player, and the result is victory/defeat, then send // a message to notify the server of the reason for the game ending. if (!obs) { config cfg; config& info = cfg.add_child("info"); info["type"] = "termination"; info["condition"] = "game over"; info["result"] = gamestate_.classification().completion; network::send_data(cfg, 0); } else { gui2::show_transient_message(gui_->video(),_("Game Over"), _("The game is over.")); return OBSERVER_END; } } if (end_level_result == QUIT) { return QUIT; } else if (end_level_result == DEFEAT) { gamestate_.classification().completion = "defeat"; game_events::fire("defeat"); if (!obs) { const std::string& defeat_music = select_defeat_music(); if(defeat_music.empty() != true) sound::play_music_once(defeat_music); return DEFEAT; } else { return QUIT; } } else if (end_level_result == VICTORY) { gamestate_.classification().completion = !end_level.linger_mode ? "running" : "victory"; game_events::fire("victory"); // // Play victory music once all victory events // are finished, if we aren't observers. // // Some scenario authors may use 'continue' // result for something that is not story-wise // a victory, so let them use [music] tags // instead should they want special music. // if (!obs && end_level.linger_mode) { const std::string& victory_music = select_victory_music(); if(victory_music.empty() != true) sound::play_music_once(victory_music); } // Add all the units that survived the scenario. LOG_NG << "Add units that survived the scenario to the recall list.\n"; for(unit_map::iterator un = units_.begin(); un != units_.end(); ++un) { if (teams_[un->side() - 1].persistent()) { LOG_NG << "Added unit " << un->id() << ", " << un->name() << "\n"; un->new_turn(); un->new_scenario(); teams_[un->side() - 1].recall_list().push_back(*un); } } //store all units that survived (recall list for the next scenario) in snapshot gamestate_.snapshot = config(); store_recalls(); //store gold and report victory store_gold(obs); return VICTORY; } else if (end_level_result == SKIP_TO_LINGER) { LOG_NG << "resuming from loaded linger state...\n"; //as carryover information is stored in the snapshot, we have to re-store it after loading a linger state gamestate_.snapshot = config(); store_recalls(); store_gold(); return VICTORY; } } // end catch catch(network::error& e) { bool disconnect = false; if(e.socket) { e.disconnect(); disconnect = true; } savegame::game_savegame save(gamestate_, *gui_, to_config(), preferences::compress_saves()); save.save_game_interactive(gui_->video(), _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), gui::YES_NO); if(disconnect) { throw network::error(); } else { return QUIT; } } return QUIT; }
LEVEL_RESULT playsingle_controller::play_scenario( const config::const_child_itors &story, bool skip_replay) { LOG_NG << "in playsingle_controller::play_scenario()...\n"; // Start music. BOOST_FOREACH(const config &m, level_.child_range("music")) { sound::play_music_config(m); } sound::commit_music_changes(); if(!skip_replay) { show_story(*gui_, level_["name"], story); } gui_->labels().read(level_); // Read sound sources assert(soundsources_manager_ != NULL); BOOST_FOREACH(const config &s, level_.child_range("sound_source")) { try { soundsource::sourcespec spec(s); soundsources_manager_->add(spec); } catch (bad_lexical_cast &) { ERR_NG << "Error when parsing sound_source config: bad lexical cast." << std::endl; ERR_NG << "sound_source config was: " << s.debug() << std::endl; ERR_NG << "Skipping this sound source..." << std::endl; } } set_victory_when_enemies_defeated(level_["victory_when_enemies_defeated"].to_bool(true)); set_remove_from_carryover_on_defeat(level_["remove_from_carryover_on_defeat"].to_bool(true)); end_level_data &end_level = get_end_level_data(); end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage); end_level.carryover_add = level_["carryover_add"].to_bool(); bool past_prestart = false; LOG_NG << "entering try... " << (SDL_GetTicks() - ticks_) << "\n"; try { possible_end_play_signal signal = play_scenario_init(end_level, past_prestart); if (!signal) { signal = play_scenario_main_loop(end_level, past_prestart); } if (signal) { switch (boost::apply_visitor( get_signal_type(), *signal )) { //BEGIN CASES case END_TURN: assert(false && "end turn signal propogated to playsingle_controller::play_scenario. This results in terminate!"); throw 42; case END_LEVEL: if(!past_prestart) { sdl::draw_solid_tinted_rectangle( 0, 0, gui_->video().getx(), gui_->video().gety(), 0, 0, 0, 1.0, gui_->video().getSurface() ); update_rect(0, 0, gui_->video().getx(), gui_->video().gety()); } ai_testing::log_game_end(); LEVEL_RESULT end_level_result = boost::apply_visitor( get_result(), *signal ); if (!end_level.transient.custom_endlevel_music.empty()) { if (end_level_result == DEFEAT) { set_defeat_music_list(end_level.transient.custom_endlevel_music); } else { set_victory_music_list(end_level.transient.custom_endlevel_music); } } if (gamestate_.board_.teams().empty()) { //store persistent teams saved_game_.set_snapshot(config()); return VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event } const bool obs = is_observer(); if (game_config::exit_at_end) { exit(0); } if (end_level_result == DEFEAT || end_level_result == VICTORY) { saved_game_.classification().completion = (end_level_result == VICTORY) ? "victory" : "defeat"; // If we're a player, and the result is victory/defeat, then send // a message to notify the server of the reason for the game ending. if (!obs) { config cfg; config& info = cfg.add_child("info"); info["type"] = "termination"; info["condition"] = "game over"; info["result"] = saved_game_.classification().completion; network::send_data(cfg, 0); } else { gui2::show_transient_message(gui_->video(),_("Game Over"), _("The game is over.")); return OBSERVER_END; } } if (end_level_result == QUIT) { return QUIT; } else if (end_level_result == DEFEAT) { saved_game_.classification().completion = "defeat"; game_events::fire("defeat"); if (!obs) { const std::string& defeat_music = select_defeat_music(); if(defeat_music.empty() != true) sound::play_music_once(defeat_music); persist_.end_transaction(); return DEFEAT; } else { return QUIT; } } else if (end_level_result == VICTORY) { saved_game_.classification().completion = !end_level.transient.linger_mode ? "running" : "victory"; game_events::fire("victory"); // // Play victory music once all victory events // are finished, if we aren't observers. // // Some scenario authors may use 'continue' // result for something that is not story-wise // a victory, so let them use [music] tags // instead should they want special music. // if (!obs && end_level.transient.linger_mode) { const std::string& victory_music = select_victory_music(); if(victory_music.empty() != true) sound::play_music_once(victory_music); } // Add all the units that survived the scenario. // this function doesn't move unit to the recalllist anymore i just keep this name to prevent merging conflicts. LOG_NG << "Add units that survived the scenario to the recall list.\n"; gamestate_.board_.all_survivors_to_recall(); saved_game_.remove_snapshot(); if(!is_observer()) { persist_.end_transaction(); } return VICTORY; } else if (end_level_result == SKIP_TO_LINGER) { LOG_NG << "resuming from loaded linger state...\n"; //as carryover information is stored in the snapshot, we have to re-store it after loading a linger state saved_game_.set_snapshot(config()); if(!is_observer()) { persist_.end_transaction(); } return VICTORY; } break; //END CASES } // END SWITCH } //end if } catch(const game::load_game_exception &) { // Loading a new game is effectively a quit. // if ( game::load_game_exception::game != "" ) { saved_game_ = saved_game(); } throw; } catch(network::error& e) { bool disconnect = false; if(e.socket) { e.disconnect(); disconnect = true; } savegame::ingame_savegame save(saved_game_, *gui_, to_config(), preferences::save_compression_format()); save.save_game_interactive(gui_->video(), _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), gui::YES_NO); if(disconnect) { throw network::error(); } else { return QUIT; } } return QUIT; }
play_controller::play_controller(const config& level, saved_game& state_of_game, const config& game_config, const ter_data_cache& tdata, CVideo& video, bool skip_replay) : controller_base(game_config, video) , observer() , quit_confirmation() , ticks_(SDL_GetTicks()) , tdata_(tdata) , gamestate_() , level_() , saved_game_(state_of_game) , tooltips_manager_() , whiteboard_manager_() , plugins_context_() , labels_manager_() , help_manager_(&game_config) , mouse_handler_(nullptr, *this) , menu_handler_(nullptr, *this, game_config) , hotkey_handler_(new hotkey_handler(*this, saved_game_)) , soundsources_manager_() , persist_() , gui_() , xp_mod_(new unit_experience_accelerator(level["experience_modifier"].to_int(100))) , statistics_context_(new statistics::scenario_context(level["name"])) , replay_(new replay(state_of_game.get_replay())) , skip_replay_(skip_replay) , linger_(false) , init_side_done_now_(false) , victory_when_enemies_defeated_(level["victory_when_enemies_defeated"].to_bool(true)) , remove_from_carryover_on_defeat_(level["remove_from_carryover_on_defeat"].to_bool(true)) , victory_music_() , defeat_music_() , scope_() , ignore_replay_errors_(false) , player_type_changed_(false) { copy_persistent(level, level_); resources::controller = this; resources::persist = &persist_; resources::recorder = replay_.get(); resources::classification = &saved_game_.classification(); resources::mp_settings = &saved_game_.mp_settings(); persist_.start_transaction(); // Setup victory and defeat music set_victory_music_list(level_["victory_music"]); set_defeat_music_list(level_["defeat_music"]); game_config::add_color_info(level); hotkey::deactivate_all_scopes(); hotkey::set_scope_active(hotkey::SCOPE_GAME); try { init(video, level); } catch (...) { clear_resources(); throw; } }