playsingle_controller::playsingle_controller(const config& level, game_state& state_of_game, hero_map& heros, hero_map& heros_start, card_map& cards, const int ticks, const int num_turns, const config& game_config, CVideo& video, bool skip_replay) : play_controller(level, state_of_game, heros, heros_start, cards, ticks, num_turns, game_config, video, skip_replay, false), cursor_setter(cursor::NORMAL), data_backlog_(), textbox_info_(), replay_sender_(recorder), end_turn_(false), player_type_changed_(false), turn_over_(false), skip_next_turn_(false), level_result_(NONE) { game_config::no_messagebox = false; game_config::hide_tactic_slot = false; // game may need to start in linger mode if (state_of_game.classification().completion == "victory" || state_of_game.classification().completion == "defeat") { LOG_NG << "Setting linger mode.\n"; browse_ = linger_ = true; } ai::game_info ai_info(*gui_, map_, units_, heros_, teams_, tod_manager_, gamestate_); ai::manager::set_ai_info(ai_info); ai::manager::add_observer(this) ; }
playsingle_controller::playsingle_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) : play_controller(level, state_of_game, ticks, num_turns, game_config, video, skip_replay), cursor_setter(cursor::NORMAL), data_backlog_(), textbox_info_(), replay_sender_(recorder), end_turn_(false), player_type_changed_(false), replaying_(false), turn_over_(false), skip_next_turn_(false), level_result_(NONE) { // game may need to start in linger mode if (state_of_game.classification().completion == "victory" || state_of_game.classification().completion == "defeat") { LOG_NG << "Setting linger mode.\n"; browse_ = linger_ = true; } ai::game_info ai_info; ai::manager::set_ai_info(ai_info); ai::manager::add_observer(this) ; }
void play_replay(display& disp, game_state& gamestate, const config& game_config, hero_map& heros, hero_map& heros_start, card_map& cards, CVideo& video) { std::string type = gamestate.classification().campaign_type; if(type.empty()) type = "scenario"; // 'starting_pos' will contain the position we start the game from. config starting_pos; if (gamestate.starting_pos.empty()){ // Backwards compatibility code for 1.2 and 1.2.1 const config &scenario = game_config.find_child(type,"id",gamestate.classification().scenario); assert(scenario); gamestate.starting_pos = scenario; } starting_pos = gamestate.starting_pos; //for replays, use the variables specified in starting_pos if (const config &vars = starting_pos.child("variables")) { gamestate.set_variables(vars); } try { // Preserve old label eg. replay if (gamestate.classification().label.empty()) gamestate.classification().label = starting_pos["name"].str(); //if (gamestate.abbrev.empty()) // gamestate.abbrev = (*scenario)["abbrev"]; play_replay_level(game_config, &starting_pos, video, gamestate, heros, heros_start, cards); gamestate.snapshot = config(); recorder.clear(); gamestate.replay_data.clear(); gamestate.start_scenario_ss.str(""); // gamestate.start_hero_ss.str(""); gamestate.clear_start_hero_data(); } catch(game::load_game_failed& e) { gui2::show_error_message(disp.video(), _("The game could not be loaded: ") + e.message); } catch(game::game_error& e) { gui2::show_error_message(disp.video(), _("Error while playing the game: ") + e.message); } catch(incorrect_map_format_error& e) { gui2::show_error_message(disp.video(), std::string(_("The game map could not be loaded: ")) + e.message); } catch(twml_exception& e) { e.show(disp); } }
replay_controller::replay_controller(const config& level, game_state& state_of_game, const int ticks, const int num_turns, const config& game_config, CVideo& video) : play_controller(level, state_of_game, ticks, num_turns, game_config, video, false), teams_start_(), gamestate_start_(state_of_game), units_start_(), tod_manager_start_(level, num_turns, &state_of_game), current_turn_(1), delay_(0), is_playing_(false), show_everything_(false), show_team_(state_of_game.classification().campaign_type == "multiplayer" ? 0 : 1) { init(); gamestate_start_ = gamestate_; }
replay_controller::replay_controller(const config& level, game_state& state_of_game, const int ticks, const int num_turns, const config& game_config, CVideo& video) : play_controller(level, state_of_game, ticks, num_turns, game_config, video, false), teams_start_(teams_), gamestate_start_(gamestate_), units_start_(units_), tod_manager_start_(level, num_turns), current_turn_(1), is_playing_(false), show_everything_(false), show_team_(state_of_game.classification().campaign_type == game_classification::MULTIPLAYER ? 0 : 1) { tod_manager_start_ = tod_manager_; // Our parent class correctly detects that we are loading a game. However, // we are not loading mid-game, so from here on, treat this as not loading // a game. (Allows turn_1 et al. events to fire at the correct time.) loading_game_ = false; init(); reset_replay(); }
scenariostart_savegame::scenariostart_savegame(game_state &gamestate, const bool compress_saves) : savegame(gamestate, compress_saves) { set_filename(gamestate.classification().label); }
LEVEL_RESULT play_game(display& disp, game_state& gamestate, const config& game_config, hero_map& heros, hero_map& heros_start, card_map& cards, io_type_t io_type, bool skip_replay) { tent::io_type = io_type; std::string type = gamestate.classification().campaign_type; if (type.empty()) { type = "scenario"; } config const* scenario = NULL; // 'starting_pos' will contain the position we start the game from. config starting_pos; // Do we have any snapshot data? // yes => this must be a savegame // no => we are starting a fresh scenario if (!gamestate.snapshot["runtime"].to_bool() || !recorder.at_end()) { gamestate.classification().completion = "running"; // Campaign or Multiplayer? // If the gamestate already contains a starting_pos, // then we are starting a fresh multiplayer game. // Otherwise this is the start of a campaign scenario. if (gamestate.starting_pos["id"].empty() == false) { starting_pos = gamestate.starting_pos; scenario = &starting_pos; } else { // reload of the scenario, as starting_pos contains carryover information only scenario = &load_campagin_scenario(gamestate.classification().campaign, gamestate.classification().scenario, type); VALIDATE(!scenario->empty(), std::string("play_game, cannot load scenario id = ") + gamestate.classification().scenario + " in game_config!"); gamestate.starting_pos = *scenario; starting_pos = gamestate.starting_pos; scenario = &starting_pos; } } else { // This game was started from a savegame starting_pos = gamestate.starting_pos; scenario = &gamestate.snapshot; // When starting wesnoth --multiplayer there might be // no variables which leads to a segfault if (const config &vars = gamestate.snapshot.child("variables")) { gamestate.set_variables(vars); } gamestate.set_menu_items(gamestate.snapshot.child_range("menu_item")); // Replace game label with that from snapshot if (!gamestate.snapshot["label"].empty()){ gamestate.classification().label = gamestate.snapshot["label"].str(); } } bool fog = scenario->get("fog")->to_bool(); bool shroud = scenario->get("shroud")->to_bool(); while (scenario != NULL) { // If we are a multiplayer client, tweak the controllers if (io_type == IO_CLIENT) { if (scenario != &starting_pos) { starting_pos = *scenario; scenario = &starting_pos; } } config::const_child_itors story = scenario->child_range("story"); gamestate.classification().next_scenario = (*scenario)["next_scenario"].str(); bool save_game_after_scenario = true; LEVEL_RESULT res = VICTORY; end_level_data end_level; try { // Preserve old label eg. replay if (gamestate.classification().label.empty()) { t_string tstr = (*scenario)["name"]; if (gamestate.classification().abbrev.empty()) { gamestate.classification().label = tstr; gamestate.classification().original_label = tstr.base_str(); } else { gamestate.classification().label = std::string(gamestate.classification().abbrev); gamestate.classification().label.append("-"); gamestate.classification().original_label = gamestate.classification().label; gamestate.classification().label.append(tstr); gamestate.classification().original_label.append(tstr.base_str()); } } // If the entire scenario should be randomly generated if ((*scenario)["scenario_generation"] != "") { const cursor::setter cursor_setter(cursor::WAIT); static config scenario2; scenario2 = random_generate_scenario((*scenario)["scenario_generation"], scenario->child("generator")); //level_ = scenario; //merge carryover information into the newly generated scenario config temp(scenario2); gamestate.starting_pos = temp; scenario = &scenario2; } std::string map_data = (*scenario)["map_data"]; if(map_data.empty() && (*scenario)["map"] != "") { map_data = read_map((*scenario)["map"]); } // If the map should be randomly generated if(map_data.empty() && (*scenario)["map_generation"] != "") { const cursor::setter cursor_setter(cursor::WAIT); map_data = random_generate_map((*scenario)["map_generation"],scenario->child("generator")); // Since we've had to generate the map, // make sure that when we save the game, // it will not ask for the map to be generated again on reload static config new_level; new_level = *scenario; new_level["map_data"] = map_data; scenario = &new_level; //merge carryover information into the scenario config temp(new_level); gamestate.starting_pos = temp; } sound::empty_playlist(); //add the variables to the starting_pos unless they are already there const config &wmlvars = gamestate.starting_pos.child("variables"); if (!wmlvars || wmlvars.empty()){ gamestate.starting_pos.clear_children("variables"); gamestate.starting_pos.add_child("variables", gamestate.get_variables()); } switch (io_type){ case IO_NONE: res = playsingle_scenario(game_config, scenario, disp, gamestate, heros, heros_start, cards, story, skip_replay, end_level); break; case IO_SERVER: case IO_CLIENT: res = playmp_scenario(game_config, scenario, disp, gamestate, heros, heros_start, cards, story, skip_replay, io_type, end_level); break; } } catch(game::load_game_failed& e) { gui2::show_error_message(disp.video(), _("The game could not be loaded: ") + e.message); return QUIT; } catch(game::game_error& e) { gui2::show_error_message(disp.video(), _("Error while playing the game: ") + e.message); return QUIT; } catch(incorrect_map_format_error& e) { gui2::show_error_message(disp.video(), std::string(_("The game map could not be loaded: ")) + e.message); return QUIT; } catch(config::error& e) { std::cerr << "caught config::error...\n"; gui2::show_error_message(disp.video(), _("Error while reading the WML: ") + e.message); return QUIT; } catch(twml_exception& e) { e.show(disp); return QUIT; } // Save-management options fire on game end. // This means: (a) we have a victory, or // or (b) we're multiplayer live, in which // case defeat is also game end. Someday, // if MP campaigns ever work again, we might // need to change this test. if (res == VICTORY || (io_type != IO_NONE && res == DEFEAT)) { if (preferences::delete_saves()) { savegame::manager::clean_saves(gamestate.classification().label); } } recorder.clear(); gamestate.replay_data.clear(); gamestate.start_scenario_ss.str(""); gamestate.clear_start_hero_data(); // On DEFEAT, QUIT, or OBSERVER_END, we're done now if (res != VICTORY) { if (res != OBSERVER_END || gamestate.classification().next_scenario.empty()) { gamestate.snapshot = config(); return res; } const int dlg_res = gui2::show_message(disp.video(), _("Game Over"), _("This scenario has ended. Do you want to continue the campaign?"), gui2::tmessage::yes_no_buttons); if (dlg_res == gui2::twindow::CANCEL) { gamestate.snapshot = config(); return res; } } // Continue without saving is like a victory, // but the save game dialog isn't displayed if (!end_level.prescenario_save) { save_game_after_scenario = false; } // Switch to the next scenario. gamestate.classification().scenario = gamestate.classification().next_scenario; gamestate.rng().rotate_random(); // gamestate.rng().seed_random(rand(), 0); scenario = NULL; if (io_type == IO_NONE) { scenario = &load_campagin_scenario(gamestate.classification().campaign, gamestate.classification().scenario, type); if (scenario->empty()) { scenario = NULL; } else{ starting_pos = *scenario; starting_pos["fog"] = fog; starting_pos["shroud"] = shroud; scenario = &starting_pos; } } if (scenario != NULL) { // to single-player campaign, there are multi-secenario, // set this result to next start hero data heros.reset_to_unstage(); heros_start = heros; loadscreen::global_loadscreen_manager* loadscreen_manager = loadscreen::global_loadscreen_manager::get(); if (loadscreen_manager) { loadscreen_manager->reset(); } // Update the label // std::string oldlabel = gamestate.classification().label; t_string scenario_name = (*scenario)["name"]; if (gamestate.classification().abbrev.empty()) { gamestate.classification().label = scenario_name; gamestate.classification().original_label = scenario_name.base_str(); } else { gamestate.classification().label = std::string(gamestate.classification().abbrev); gamestate.classification().label.append("-"); gamestate.classification().original_label = gamestate.classification().label; gamestate.classification().label.append(scenario_name); gamestate.classification().original_label.append(scenario_name.base_str()); } // If this isn't the last scenario, then save the game if (save_game_after_scenario) { // For multiplayer, we want the save // to contain the starting position. // For campaigns however, this is the // start-of-scenario save and the // starting position needs to be empty, // to force a reload of the scenario config. if (gamestate.classification().campaign_type != "multiplayer"){ gamestate.starting_pos = config(); } //add the variables to the starting position gamestate.starting_pos.add_child("variables", gamestate.get_variables()); savegame::scenariostart_savegame save(heros, heros_start, gamestate); save.save_game_automatic(disp.video()); } if (gamestate.classification().campaign_type != "multiplayer"){ gamestate.starting_pos = *scenario; //add the variables to the starting position gamestate.starting_pos.add_child("variables", gamestate.get_variables()); } gamestate.start_scenario_ss.str(""); } gamestate.snapshot = config(); } if (!gamestate.classification().scenario.empty() && gamestate.classification().scenario != "null") { std::string message = _("Unknown scenario: '$scenario|'"); utils::string_map symbols; symbols["scenario"] = gamestate.classification().scenario; message = utils::interpolate_variables_into_string(message, &symbols); gui2::show_error_message(disp.video(), message); return QUIT; } if (gamestate.classification().campaign_type == "scenario"){ if (preferences::delete_saves()) { savegame::manager::clean_saves(gamestate.classification().label); } } return VICTORY; }
scenariostart_savegame::scenariostart_savegame(hero_map& heros, hero_map& heros_start, game_state &gamestate) : savegame(heros, heros_start, gamestate, dummy_snapshot) { memset(game_config::savegame_cache, 0, sizeof(unit_segment2)); set_filename(gamestate.classification().label); }