void holder::modify_ai(const config &cfg) { if (!this->ai_) { // if not initialized, initialize now. get_ai_ref(); } const std::string &act = cfg["action"]; LOG_AI_MOD << "side "<< side_ << " [modify_ai] "<<act<<" \""<<cfg["path"]<<"\""<<std::endl; DBG_AI_MOD << std::endl << cfg << std::endl; DBG_AI_MOD << "side "<< side_ << " before [modify_ai]"<<std::endl << to_config() << std::endl; bool res = false; if (act == "add") { res = component_manager::add_component(&*this->ai_,cfg["path"],cfg); } else if (act == "change") { res = component_manager::change_component(&*this->ai_,cfg["path"],cfg); } else if (act == "delete") { res = component_manager::delete_component(&*this->ai_,cfg["path"]); } else if (act == "try_delete") { res = component_manager::delete_component(&*this->ai_,cfg["path"]); if (!res) { LOG_AI_MOD << "[modify_ai] "<<act<<" failed, ignoring because it's a try_delete"<< std::endl; res = true; } } else { ERR_AI_MOD << "modify_ai tag has invalid 'action' attribute " << act << std::endl; } DBG_AI_MOD << "side "<< side_ << " after [modify_ai]"<<act<<std::endl << to_config() << std::endl; if (!res) { LOG_AI_MOD << "[modify_ai] "<<act<<" failed"<< std::endl; } else { LOG_AI_MOD << "[modify_ai] "<<act<<" success"<< std::endl; } }
void playmp_controller::process_oos(const std::string& err_msg) const { // Notify the server of the oos error. config cfg; config& info = cfg.add_child("info"); info["type"] = "termination"; info["condition"] = "out of sync"; network::send_data(cfg, 0); std::stringstream temp_buf; std::vector<std::string> err_lines = utils::split(err_msg,'\n'); temp_buf << _("The game is out of sync, and cannot continue. There are a number of reasons this could happen: this can occur if you or another player have modified their game settings. This may mean one of the players is attempting to cheat. It could also be due to a bug in the game, but this is less likely.\n\nDo you want to save an error log of your game?"); if(!err_msg.empty()) { temp_buf << " \n \n"; //and now the "Details:" for(std::vector<std::string>::iterator i=err_lines.begin(); i!=err_lines.end(); ++i) { temp_buf << "`#" << *i << '\n'; } temp_buf << " \n"; } config snapshot; to_config(snapshot); savegame::oos_savegame save(heros_, snapshot); save.save_game_interactive(resources::screen->video(), temp_buf.str(), gui::YES_NO); }
void playsingle_controller::before_human_turn(bool save) { browse_ = false; linger_ = false; gui_->refresh_access_troops(player_number_ - 1); gui_->refresh_access_heros(player_number_ - 1); ai::manager::raise_turn_started(); if (save) { // uint32_t start = SDL_GetTicks(); config snapshot; to_config(snapshot); // uint32_t mid1 = SDL_GetTicks(); // posix_print("(mid1)used time: %u ms\n", mid1 - start); savegame::autosave_savegame save(heros_, heros_start_, gamestate_, *gui_, snapshot); // uint32_t mid2 = SDL_GetTicks(); // posix_print("(mid2)used time: %u ms\n", mid2 - mid1); save.autosave(game_config::disable_autosave, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES); // uint32_t mid3 = SDL_GetTicks(); // posix_print("(mid3)used time: %u ms\n", mid3 - mid2); } else { teams_[player_number_ - 1].refresh_tactic_slots(*gui_); } if (preferences::turn_bell()) { sound::play_bell(game_config::sounds::turn_bell); } // button: undo undo_stack_.clear(); if (teams_[player_number_-1].uses_shroud() || teams_[player_number_-1].uses_fog()) { gui_->hide_menu("undo", true); } else { gui_->hide_menu("undo", false); gui_->enable_menu("undo", false); } // button: endturn gui_->enable_menu("play_card", true); gui_->enable_menu("endturn", true); /* if (rpg::stratum == hero_stratum_leader) { if (card_mode_) { execute_card_uh(turn(), player_number_); } execute_guard_attack(player_number_); } */ // card refresh_card_button(current_team(), *gui_); // if (!network::nconnections()) { // show_context_menu(NULL, *gui_); // } else { // Multiplayer mod, there is context-button when network player playing. // In order to display correct, need hide "before" button. gui_->goto_main_context_menu(); // } }
void replay_controller::process_oos(const std::string& msg) const { if (game_config::ignore_replay_errors) return; std::stringstream message; message << _("The replay is corrupt/out of sync. It might not make much sense to continue. Do you want to save the game?"); message << "\n\n" << _("Error details:") << "\n\n" << msg; savegame::oos_savegame save(to_config()); save.save_game_interactive(resources::screen->video(), message.str(), gui::YES_NO); // can throw end_level_exception }
possible_end_play_signal playsingle_controller::play_scenario_init(end_level_data & /*eld*/, bool & past_prestart) { // At the beginning of the scenario, save a snapshot as replay_start if(saved_game_.replay_start().empty()) { saved_game_.replay_start() = to_config(); } HANDLE_END_PLAY_SIGNAL( fire_preload() ); replaying_ = (recorder.at_end() == false); if(!loading_game_ ) { if(replaying_) { //can this codepath be reached ? //note this when we are entering an mp game and see the 'replay' of the game //this path is not reached because we receive the replay later config* pstart = recorder.get_next_action(); assert(pstart->has_child("start")); } else { assert(recorder.empty()); recorder.add_start(); recorder.get_next_action(); } //we can only use a set_scontext_synced with a non empty recorder. set_scontext_synced sync; HANDLE_END_PLAY_SIGNAL( fire_prestart() ); init_gui(); past_prestart = true; LOG_NG << "first_time..." << (recorder.is_skipping() ? "skipping" : "no skip") << "\n"; events::raise_draw_event(); HANDLE_END_PLAY_SIGNAL( fire_start(true) ); gui_->recalculate_minimap(); } else { init_gui(); past_prestart = true; events::raise_draw_event(); HANDLE_END_PLAY_SIGNAL( fire_start(false) ); gui_->recalculate_minimap(); } return boost::none; }
void playsingle_controller::play_scenario_init(const config& level) { // At the beginning of the scenario, save a snapshot as replay_start if(saved_game_.replay_start().empty()){ saved_game_.replay_start() = to_config(); } start_game(level); if( saved_game_.classification().random_mode != "" && (network::nconnections() != 0)) { // This won't cause errors later but we should notify the user about it in case he didn't knew it. gui2::show_transient_message( gui_->video(), // TODO: find a better title _("Game Error"), _("This multiplayer game uses an alternative random mode, if you don't know what this message means, then most likely someone is cheating or someone reloaded a corrupt game.") ); } return; }
void playsingle_controller::before_human_turn(bool save) { log_scope("player turn"); browse_ = false; linger_ = false; ai::manager::raise_turn_started(); if(save && level_result_ == NONE) { savegame::autosave_savegame save(gamestate_, *gui_, to_config(), preferences::save_compression_format()); save.autosave(game_config::disable_autosave, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES); } if(preferences::turn_bell() && level_result_ == NONE) { sound::play_bell(game_config::sounds::turn_bell); } }
possible_end_play_signal playsingle_controller::before_human_turn() { log_scope("player turn"); browse_ = false; linger_ = false; HANDLE_END_PLAY_SIGNAL( ai::manager::raise_turn_started() ); //This line throws exception from here: https://github.com/wesnoth/wesnoth/blob/ac96a2b91b3276e20b682210617cf87d1e0d366a/src/playsingle_controller.cpp#L954 if(do_autosaves_ && level_result_ == NONE) { savegame::autosave_savegame save(saved_game_, *gui_, to_config(), preferences::save_compression_format()); save.autosave(game_config::disable_autosave, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES); } if(preferences::turn_bell() && level_result_ == NONE) { sound::play_bell(game_config::sounds::turn_bell); } return boost::none; }
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::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; }
void play_controller::update_savegame_snapshot() const { //note: this writes to level_ if this is not a replay. this->saved_game_.set_snapshot(to_config()); }
void playsingle_controller::before_human_turn(bool save) { team& t = current_team(); if (pause_when_human_) { browse_ = false; } linger_ = false; if (gui_->access_is_null(game_display::taccess_list::TROOP)) { // change resolution will result to enter it. gui_->refresh_access_troops(player_number_ - 1, game_display::REFRESH_RELOAD); } if (!tent::tower_mode() && !preferences::developer()) { gui_->refresh_access_troops(player_number_ - 1, game_display::REFRESH_HIDE, NULL); } gui_->refresh_access_heros(player_number_ - 1, game_display::REFRESH_RELOAD); ai::manager::raise_turn_started(); if (tent::mode != mode_tag::LAYOUT && save) { autosave_ticks_ = unit_map::main_ticks; config snapshot; to_config(snapshot); savegame::autosave_savegame save(heros_, heros_start_, gamestate_, *gui_, snapshot); save.autosave(game_config::disable_autosave, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES); if (tent::turn_based) { const std::vector<hero*>& last_active_tactic = t.last_active_tactic(); for (std::vector<hero*>::const_iterator it = last_active_tactic.begin(); it != last_active_tactic.end(); ++ it) { hero& selected_hero = **it; unit* tactician = units_.find_unit(selected_hero); if (tactician && !tactician->is_resided()) { do_add_active_tactic(*tactician, selected_hero, true); } } } // autosave ticks changed, refresh top panel. gui_->invalidate_game_status(); } else { teams_[player_number_ - 1].refresh_tactic_slots(*gui_); } if (unit::actor && unit::actor->is_city()) { if (preferences::turn_bell()) { sound::play_bell(game_config::sounds::turn_bell); } if (game_config::show_side_report) { gui2::tside_report dlg(*gui_, teams_, units_, heros_, unit::actor->side()); dlg.show(gui_->video()); } } // button: undo undo_stack_.clear(); if (teams_[player_number_-1].uses_shroud() || teams_[player_number_-1].uses_fog()) { gui_->set_theme_object_visible("undo", gui2::twidget::INVISIBLE); } else { gui_->set_theme_object_visible("undo", gui2::twidget::VISIBLE); gui_->set_theme_object_active("undo", false); } // button: endturn if (tent::mode == mode_tag::SIEGE) { if (pause_when_human_) { refresh_endturn_button(*gui_, "buttons/ctrl-play.png"); gui_->set_theme_object_active("endturn", true); } } else if (tent::mode != mode_tag::LAYOUT) { gui_->set_theme_object_active("card", true); gui_->set_theme_object_active("endturn", true); } else { gui_->set_theme_object_visible("card", gui2::twidget::INVISIBLE); gui_->set_theme_object_visible("endturn", gui2::twidget::INVISIBLE); } // card refresh_card_button(t, *gui_); // if (!network::nconnections()) { // gui_->show_context_menu(); // } else { // Multiplayer mod, there is context-button when network player playing. // In order to display correct, need hide "before" button. gui_->goto_main_context_menu(); // } }