possible_end_play_signal playsingle_controller::check_time_over() { bool b = gamestate_.tod_manager_.next_turn(*resources::gamedata); it_is_a_new_turn_ = true; if(!b) { LOG_NG << "firing time over event...\n"; game_events::fire("time over"); LOG_NG << "done firing time over event...\n"; //if turns are added while handling 'time over' event if (gamestate_.tod_manager_.is_time_left()) { return boost::none; } if(non_interactive()) { LOG_AIT << "time over (draw)\n"; ai_testing::log_draw(); } HANDLE_END_PLAY_SIGNAL( check_victory() ); get_end_level_data().proceed_to_next_level = false; end_level_struct els = {DEFEAT}; return possible_end_play_signal (els); //throw end_level_exception(DEFEAT); } return boost::none; }
void playsingle_controller::linger() { LOG_NG << "beginning end-of-scenario linger\n"; browse_ = true; linger_ = true; // If we need to set the status depending on the completion state // the key to it is here. gui_->set_game_mode(game_display::LINGER_SP); // this is actually for after linger mode is over -- we don't // want to stay stuck in linger state when the *next* scenario // is over. set_completion setter(gamestate_,"running"); // change the end-turn button text to its alternate label gui_->get_theme().refresh_title2("button-endturn", "title2"); gui_->invalidate_theme(); gui_->redraw_everything(); // End all unit moves for (unit_map::iterator u = units_.begin(); u != units_.end(); ++u) { u->set_user_end_turn(true); } start_pass_scenario_anim(get_end_level_data().result); try { // Same logic as single-player human turn, but // *not* the same as multiplayer human turn. gui_->enable_menu("endturn", true); while(!end_turn_) { // Reset the team number to make sure we're the right team. player_number_ = first_player_; play_slice(); gui_->draw(); } } catch(game::load_game_exception& lge) { // Loading a new game is effectively a quit. if (lge.game != "") { gamestate_ = game_state(); } throw lge; } if (gui_->pass_scenario_anim_id() != -1) { gui_->erase_screen_anim(gui_->pass_scenario_anim_id()); } // revert the end-turn button text to its normal label gui_->get_theme().refresh_title2("button-endturn", "title"); gui_->invalidate_theme(); gui_->redraw_everything(); gui_->set_game_mode(game_display::RUNNING); LOG_NG << "ending end-of-scenario linger\n"; }
void playsingle_controller::report_victory( std::ostringstream &report, int player_gold, int remaining_gold, int finishing_bonus_per_turn, int turns_left, int finishing_bonus) { end_level_data &end_level = get_end_level_data(); report << _("Remaining gold: ") << remaining_gold << "\n"; if(end_level.gold_bonus) { if (turns_left > -1) { report << _("Early finish bonus: ") << finishing_bonus_per_turn << " " << _("per turn") << "\n" << "<b>" << _("Turns finished early: ") << turns_left << "</b>\n" << _("Bonus: ") << finishing_bonus << "\n"; } report << _("Gold: ") << (remaining_gold + finishing_bonus); } if (remaining_gold > 0) { report << '\n' << _("Carry over percentage: ") << end_level.carryover_percentage; } if(end_level.carryover_add) { report << "\n<b>" << _("Bonus Gold: ") << player_gold <<"</b>"; } else { report << "\n<b>" << _("Retained Gold: ") << player_gold << "</b>"; } std::string goldmsg; utils::string_map symbols; symbols["gold"] = lexical_cast_default<std::string>(player_gold); // Note that both strings are the same in english, but some languages will // want to translate them differently. if(end_level.carryover_add) { goldmsg = vngettext( "You will start the next scenario with $gold " "on top of the defined minimum starting gold.", "You will start the next scenario with $gold " "on top of the defined minimum starting gold.", player_gold, symbols); } else { goldmsg = vngettext( "You will start the next scenario with $gold " "or its defined minimum starting gold, " "whichever is higher.", "You will start the next scenario with $gold " "or its defined minimum starting gold, " "whichever is higher.", player_gold, symbols); } // xgettext:no-c-format report << '\n' << goldmsg; }
void playsingle_controller::linger() { mouse_handler_.do_right_click(false); browse_ = true; linger_ = true; // If we need to set the status depending on the completion state // the key to it is here. gui_->set_game_mode(game_display::LINGER_SP); // this is actually for after linger mode is over -- we don't // want to stay stuck in linger state when the *next* scenario // is over. set_completion setter(gamestate_,"running"); // change the end-turn button text to its alternate label gui_->redraw_everything(); // button be reconstruct. if (lobby->chat.ready()) { refresh_chat_button(*gui_, "misc/network-disconnected.png"); } start_pass_scenario_anim(get_end_level_data().result); try { // Same logic as single-player human turn, but // *not* the same as multiplayer human turn. gui_->set_theme_object_active("endturn", true); while(!end_turn_) { // Reset the team number to make sure we're the right team. player_number_ = first_player_; play_slice(); gui_->draw(); } } catch(game::load_game_exception& lge) { // Loading a new game is effectively a quit. if (lge.game != "") { gamestate_ = game_state(); } throw lge; } if (gui_->pass_scenario_anim_id() != -1) { gui_->erase_area_anim(gui_->pass_scenario_anim_id()); } // revert the end-turn button text to its normal label gui_->redraw_everything(); gui_->set_game_mode(game_display::RUNNING); LOG_NG << "ending end-of-scenario linger\n"; }
void playsingle_controller::check_end_level() { if (level_result_ == NONE || linger_) { const team &t = gamestate_.board_.teams()[gui_->viewing_team()]; if (!browse_ && t.objectives_changed()) { dialogs::show_objectives(level_, t.objectives()); t.reset_objectives_changed(); } return; } get_end_level_data().proceed_to_next_level = (level_result_ == VICTORY); throw end_level_exception(level_result_); }
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; }
void playsingle_controller::store_gold(bool obs) { bool has_next_scenario = !gamestate_.classification().next_scenario.empty() && gamestate_.classification().next_scenario != "null"; std::ostringstream report; std::string title; if (obs) { title = _("Scenario Report"); } else { persist_.end_transaction(); title = _("Victory"); report << help::tintegrate::generate_format(_("You have emerged victorious!"), "green") << "\n\n"; } end_level_data &end_level = get_end_level_data(); if (has_next_scenario || gamestate_.classification().campaign_type == "test") { int finishing_bonus_per_turn = map_.villages().size() * game_config::village_income + game_config::base_income; int turns_left = std::max<int>(0, tod_manager_.number_of_turns() - turn()); int finishing_bonus = (end_level.gold_bonus && turns_left > -1) ? finishing_bonus_per_turn * turns_left : 0; BOOST_FOREACH (const team &t, teams_) { if (true) continue; int carryover_gold = div100rounded((t.gold() + finishing_bonus) * end_level.carryover_percentage); config::child_itors side_range = gamestate_.snapshot.child_range("side"); config::child_iterator side_it = side_range.first; // Check if this side already exists in the snapshot. while (side_it != side_range.second) { if ((*side_it)["save_id"] == t.save_id()) { (*side_it)["gold"] = str_cast<int>(carryover_gold); (*side_it)["gold_add"] = end_level.carryover_add; (*side_it)["color"] = t.color(); (*side_it)["current_player"] = t.current_player(); (*side_it)["name"] = t.name(); break; } ++side_it; } // If it doesn't, add a new child. if (side_it == side_range.second) { config &new_side = gamestate_.snapshot.add_child("side"); new_side["save_id"] = t.save_id(); new_side["gold"] = str_cast<int>(carryover_gold); new_side["gold_add"] = end_level.carryover_add; new_side["color"] = t.color(); new_side["current_player"] = t.current_player(); new_side["name"] = t.name(); } // Only show the report for ourselves. if (!t.is_human()) continue; report_victory(report, carryover_gold, t.gold(), finishing_bonus_per_turn, turns_left, finishing_bonus); } }
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 playmp_controller::linger() { LOG_NG << "beginning end-of-scenario linger\n"; browse_ = true; linger_ = true; // If we need to set the status depending on the completion state // we're needed here. gui_->set_game_mode(game_display::LINGER_MP); // this is actually for after linger mode is over -- we don't want to // stay stuck in linger state when the *next* scenario is over. gamestate_.classification().completion = "running"; // End all unit moves for (unit_map::iterator u = units_.begin(); u != units_.end(); ++ u) { u->set_user_end_turn(true); } //current_team().set_countdown_time(0); //halt and cancel the countdown timer reset_countdown(); set_end_scenario_button(); if ( get_end_level_data().reveal_map ) { // switch to observer viewpoint gui_->set_team(0,true); gui_->recalculate_minimap(); gui_->invalidate_all(); gui_->draw(true,true); } bool quit; do { quit = true; try { // reimplement parts of play_side() player_number_ = first_player_; init_turn_data(); play_human_turn(); turn_over_ = true; // We don't want to linger mode to add end_turn to replay after_human_turn(); LOG_NG << "finished human turn" << std::endl; } catch (game::load_game_exception&) { LOG_NG << "caught load-game-exception" << std::endl; // this should not happen, the option to load a game is disabled throw; } catch (end_level_exception&) { // thrown if the host ends the scenario and let us advance // to the next level LOG_NG << "caught end-level-exception" << std::endl; reset_end_scenario_button(); throw; } catch (end_turn_exception&) { // thrown if the host leaves the game (sends [leave_game]), we need // to stay in this loop to stay in linger mode, otherwise the game // gets aborted LOG_NG << "caught end-turn-exception" << std::endl; quit = false; } catch (network::error&) { LOG_NG << "caught network-error-exception" << std::endl; quit = false; } } while (!quit); reset_end_scenario_button(); LOG_NG << "ending end-of-scenario linger\n"; }