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 replay_controller::reset_replay() { DBG_REPLAY << "replay_controller::reset_replay\n"; gui_->clear_chat_messages(); is_playing_ = false; player_number_ = 1; current_turn_ = 1; it_is_a_new_turn_ = true; skip_replay_ = false; tod_manager_= tod_manager_start_; recorder.start_replay(); recorder.set_skip(false); units_ = units_start_; gamestate_ = gamestate_start_; teams_ = teams_start_; if (events_manager_ ){ // NOTE: this double reset is required so that the new // instance of game_events::manager isn't created before the // old manager is actually destroyed (triggering an assertion // failure) events_manager_.reset(); events_manager_.reset(new game_events::manager(level_)); } gui_->labels().read(level_); resources::gamedata->rng().seed_random(level_["random_seed"], level_["random_calls"]); statistics::fresh_stats(); set_victory_when_enemies_defeated(level_["victory_when_enemies_defeated"].to_bool(true)); // Add era events for MP game. if (const config &era_cfg = level_.child("era")) { game_events::add_events(era_cfg.child_range("event"), "era_events"); } // Scenario initialization. (c.f. playsingle_controller::play_scenario()) fire_preload(); if(true){ //block for set_scontext_synced config* pstart = recorder.get_next_action(); assert(pstart->has_child("start")); /* use this after recorder.add_synced_command because set_scontext_synced sets the checkup to the last added command */ set_scontext_synced sync; fire_prestart(true); init_gui(); fire_start(true); } // Since we did not fire the start event, it_is_a_new_turn_ has the wrong value. it_is_a_new_turn_ = true; update_gui(); reset_replay_ui(); }
void play_controller::start_game() { fire_preload(); if(!gamestate().start_event_fired_) { gamestate().start_event_fired_ = true; resources::recorder->add_start_if_not_there_yet(); resources::recorder->get_next_action(); set_scontext_synced sync; fire_prestart(); if (is_regular_game_end()) { return; } for ( int side = gamestate().board_.teams().size(); side != 0; --side ) actions::clear_shroud(side, false, false); init_gui(); LOG_NG << "first_time..." << (is_skipping_replay() ? "skipping" : "no skip") << "\n"; events::raise_draw_event(); fire_start(); if (is_regular_game_end()) { return; } sync.do_final_checkup(); gui_->recalculate_minimap(); // Initialize countdown clock. for (const team& t : gamestate().board_.teams()) { if (saved_game_.mp_settings().mp_countdown) { t.set_countdown_time(1000 * saved_game_.mp_settings().mp_countdown_init_time); } } } else { init_gui(); events::raise_draw_event(); gamestate().gamedata_.set_phase(game_data::PLAY); gui_->recalculate_minimap(); } }
void replay_controller::init(){ DBG_REPLAY << "in replay_controller::init()...\n"; //guarantee the cursor goes back to 'normal' at the end of the level const cursor::setter cursor_setter(cursor::NORMAL); init_replay_display(); fire_prestart(true); init_gui(); statistics::fresh_stats(); set_victory_when_enemies_defeated( utils::string_bool(level_["victory_when_enemies_defeated"], true)); DBG_REPLAY << "first_time..." << (recorder.is_skipping() ? "skipping" : "no skip") << "\n"; fire_start(!loading_game_); update_gui(); units_start_ = units_; teams_start_ = teams_; }
void replay_controller::reset_replay(){ gui_->clear_chat_messages(); is_playing_ = false; player_number_ = 1; current_turn_ = 1; skip_replay_ = false; tod_manager_= tod_manager_start_; recorder.start_replay(); recorder.set_skip(false); units_ = units_start_; gamestate_ = gamestate_start_; teams_ = teams_start_; statistics::fresh_stats(); if (events_manager_ ){ // NOTE: this double reset is required so that the new // instance of game_events::manager isn't created before the // old manager is actually destroyed (triggering an assertion // failure) events_manager_.reset(); events_manager_.reset(new game_events::manager(level_)); } gui_->new_turn(); gui_->invalidate_game_status(); events::raise_draw_event(); (*gui_).invalidate_all(); (*gui_).draw(); fire_prestart(true); fire_start(!loading_game_); gui_->new_turn(); gui_->invalidate_game_status(); events::raise_draw_event(); (*gui_).invalidate_all(); (*gui_).draw(); gui_->set_team(player_number_-1, show_everything_); //gui_->scroll_to_leader(units_, player_number_,game_display::ONSCREEN,false); buttons_.reset_buttons(); }
void replay_controller::reset_replay(){ gui::button* b = gui_->find_button("button-playreplay"); if (b != NULL) { b->release(); } b = gui_->find_button("button-stopreplay"); if (b != NULL) { b->release(); } gui_->clear_chat_messages(); is_playing_ = false; player_number_ = 1; current_turn_ = 1; tod_manager_= tod_manager_start_; recorder.start_replay(); units_ = units_start_; gamestate_ = gamestate_start_; teams_ = teams_start_; statistics::fresh_stats(); if (events_manager_ ){ // NOTE: this double reset is required so that the new // instance of game_events::manager isn't created before the // old manager is actually destroyed (triggering an assertion // failure) events_manager_.reset(); events_manager_.reset(new game_events::manager(level_)); } gui_->new_turn(); gui_->invalidate_game_status(); events::raise_draw_event(); (*gui_).invalidate_all(); (*gui_).draw(); fire_prestart(true); fire_start(!loading_game_); gui_->new_turn(); gui_->invalidate_game_status(); events::raise_draw_event(); (*gui_).invalidate_all(); (*gui_).draw(); b = gui_->find_button("button-resetreplay"); if (b != NULL) { b->release(); } }
void replay_controller::reset_replay(){ gui_->clear_chat_messages(); is_playing_ = false; player_number_ = 1; current_turn_ = 1; it_is_a_new_turn_ = true; skip_replay_ = false; tod_manager_= tod_manager_start_; recorder.start_replay(); recorder.set_skip(false); units_ = units_start_; gamestate_ = gamestate_start_; teams_ = teams_start_; if (events_manager_ ){ // NOTE: this double reset is required so that the new // instance of game_events::manager isn't created before the // old manager is actually destroyed (triggering an assertion // failure) events_manager_.reset(); events_manager_.reset(new game_events::manager(level_)); } gui_->labels().read(level_); statistics::fresh_stats(); set_victory_when_enemies_defeated(level_["victory_when_enemies_defeated"].to_bool(true)); // Add era events for MP game. if (const config &era_cfg = level_.child("era")) { game_events::add_events(era_cfg.child_range("event"), "era_events"); } fire_prestart(true); init_gui(); fire_start(true); update_gui(); reset_replay_ui(); }
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; }
void replay_controller::reset_replay() { DBG_REPLAY << "replay_controller::reset_replay\n"; gui_->get_chat_manager().clear_chat_messages(); is_playing_ = false; player_number_ = 1; current_turn_ = 1; it_is_a_new_turn_ = true; skip_replay_ = false; gamestate_.tod_manager_= tod_manager_start_; recorder.start_replay(); recorder.set_skip(false); saved_game_ = saved_game_start_; gamestate_.board_ = gameboard_start_; gui_->change_display_context(&gamestate_.board_); //this doesn't change the pointer value, but it triggers the gui to update the internal terrain builder object, //idk what the consequences of not doing that are, but its probably a good idea to do it, esp. if layout //of game_board changes in the future if (events_manager_ ){ // NOTE: this double reset is required so that the new // instance of game_events::manager isn't created before the // old manager is actually destroyed (triggering an assertion // failure) events_manager_.reset(); events_manager_.reset(new game_events::manager(level_)); } gui_->labels().read(level_); resources::gamedata->rng().seed_random(level_["random_seed"], level_["random_calls"]); statistics::fresh_stats(); set_victory_when_enemies_defeated(level_["victory_when_enemies_defeated"].to_bool(true)); resources::screen->recalculate_minimap(); resources::screen->invalidate_all(); resources::screen->rebuild_all(); // Add era events for MP game. if (const config &era_cfg = level_.child("era")) { game_events::add_events(era_cfg.child_range("event"), "era_events"); } // Scenario initialization. (c.f. playsingle_controller::play_scenario()) fire_preload(); if(true){ //block for set_scontext_synced if(recorder.add_start_if_not_there_yet()) { ERR_REPLAY << "inserted missing [start]" << std::endl; } config* pstart = recorder.get_next_action(); assert(pstart->has_child("start")); /* use this after recorder.add_synced_command because set_scontext_synced sets the checkup to the last added command */ set_scontext_synced sync; fire_prestart(); init_gui(); fire_start(true); } // Since we did not fire the start event, it_is_a_new_turn_ has the wrong value. it_is_a_new_turn_ = true; update_gui(); reset_replay_ui(); }