예제 #1
0
static bool enter_connect_mode(game_display& disp, const config& game_config,
	game_state& state, const mp_game_settings& params,
	bool local_players_only = false)
{
	DBG_MP << "entering connect mode" << std::endl;

	mp::ui::result res;
	const network::manager net_manager(1,1);
	network_game_manager m;

	gamelist.clear();
	statistics::fresh_stats();

	{
		mp::connect_engine_ptr connect_engine(new mp::connect_engine(disp,
			state, params, local_players_only, true));
		mp::connect ui(disp, params.name, game_config, gamechat, gamelist,
			*connect_engine);
		run_lobby_loop(disp, ui);

		res = ui.get_result();

		// start_game() updates the parameters to reflect game start,
		// so it must be called before get_level()
		if (res == mp::ui::PLAY) {
			ui.start_game();
		}
	}

	switch (res) {
	case mp::ui::PLAY:
		play_game(disp, state, game_config, IO_SERVER, false,
			!local_players_only);
		recorder.clear();

		break;
	case mp::ui::CREATE:
		enter_create_mode(disp, game_config, state, local_players_only);
		break;
	case mp::ui::QUIT:
	default:
		network::send_data(config("refresh_lobby"), 0);
		return false;
	}

	return true;
}
예제 #2
0
LEVEL_RESULT campaign_controller::play_game()
{
	if(is_replay_) {
		state_.get_replay().set_pos(0);
	}
	else {
		state_.get_replay().set_to_end();
	}

	state_.expand_scenario();

	game_classification::CAMPAIGN_TYPE game_type = state_.classification().campaign_type;

	while(state_.valid())
	{
		LEVEL_RESULT res = LEVEL_RESULT::VICTORY;
		end_level_data end_level;
		try {

			state_.expand_random_scenario();
			//In case this an mp scenario reloaded by sp this was not already done yet.
			state_.expand_mp_events();

			sound::empty_playlist();

			state_.expand_carryover();
			//expand_mp_options must be called after expand_carryover because expand_carryover will to set previous variables if there are already variables in the [scenario]
			state_.expand_mp_options();

#if !defined(ALWAYS_USE_MP_CONTROLLER)
			if (game_type != game_classification::CAMPAIGN_TYPE::MULTIPLAYER || is_replay_) {
				res = playsingle_scenario(end_level);
				if(is_replay_) {
					return res;
				}
			} else
#endif
			{
				res = playmp_scenario(end_level);
			}
		} catch(game::load_game_failed& e) {
			gui2::show_error_message(video_, _("The game could not be loaded: ") + e.message);
			return LEVEL_RESULT::QUIT;
		} catch(quit_game_exception&) {
			LOG_NG << "The game was aborted\n";
			return LEVEL_RESULT::QUIT;
		} catch(game::game_error& e) {
			gui2::show_error_message(video_, _("Error while playing the game: ") + e.message);
			return LEVEL_RESULT::QUIT;
		} catch(incorrect_map_format_error& e) {
			gui2::show_error_message(video_, std::string(_("The game map could not be loaded: ")) + e.message);
			return LEVEL_RESULT::QUIT;
		} catch (mapgen_exception& e) {
			gui2::show_error_message(video_, std::string(_("Map generator error: ") + e.message));
		} catch(config::error& e) {
			gui2::show_error_message(video_, _("Error while reading the WML: ") + e.message);
			return LEVEL_RESULT::QUIT;
		} catch(twml_exception& e) {
			e.show(video_);
			return LEVEL_RESULT::QUIT;
		}

		if (is_unit_test_) {
			return res;
		}
		if(res == LEVEL_RESULT::QUIT) {
			return res;
		}
		// proceed_to_next_level <=> 'any human side recieved victory'
		// If 'any human side recieved victory' we do the Save-management options
		// Otherwise we are done now
		if(!end_level.proceed_to_next_level) {
			return res;
		}

		if (preferences::delete_saves()) {
			savegame::clean_saves(state_.classification().label);
		}
		if (preferences::save_replays() && end_level.replay_save) {
			savegame::replay_savegame save(state_, preferences::save_compression_format());
			save.save_game_automatic(video_, true);
		}

		state_.convert_to_start_save();

		//If there is no next scenario we're done now.
		if(state_.get_scenario_id().empty())
		{
			return res;
		}
		else if(res == LEVEL_RESULT::OBSERVER_END && mp_info_ && !mp_info_->is_host)
		{
			const int dlg_res = gui2::show_message(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) {
				return res;
			}
		}

		if (mp_info_ && !mp_info_->is_host) {
			// Opens mp::connect dialog to get a new gamestate.
			mp::ui::result wait_res = mp::goto_mp_wait(video_, state_,
				game_config_, &mp_info_->wesnothd_connection, res == LEVEL_RESULT::OBSERVER_END);
			if (wait_res == mp::ui::QUIT) {
				return LEVEL_RESULT::QUIT;
			}

			//The host should send the complete savegame now that also contains the carryvoer sides start.
		} else {
			// Retrieve next scenario data.
			state_.expand_scenario();

			if (state_.valid()) {
				//note that although starting_pos is const it might be changed by gamestate.some_non_const_operation()  .
				const config& starting_pos = state_.get_starting_pos();

				const bool is_mp = state_.classification().is_normal_mp_game();
				state_.mp_settings().num_turns = starting_pos["turns"].to_int(-1);
				state_.mp_settings().saved_game = false;
				state_.mp_settings().use_map_settings = starting_pos["force_lock_settings"].to_bool(!is_mp);

				ng::connect_engine_ptr connect_engine(new ng::connect_engine(state_, false, mp_info_));

				if (!connect_engine->can_start_game() || (game_config::debug && game_type == game_classification::CAMPAIGN_TYPE::MULTIPLAYER)) {
					// Opens mp::connect dialog to allow users to make an adjustments for scenario.
					mp::ui::result connect_res = mp::goto_mp_connect(video_,
						*connect_engine, game_config_, mp_info_ ? &mp_info_->wesnothd_connection : nullptr, state_.mp_settings().name);
					if (connect_res == mp::ui::QUIT) {
						return LEVEL_RESULT::QUIT;
					}
				} else {
					// Start the next scenario immediately.
					connect_engine->start_game();
				}
			}
		}

		if(state_.valid()) {
			// Update the label
			state_.update_label();

			// If this isn't the last scenario, then save the game
			if(end_level.prescenario_save) {

				// 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.

				savegame::scenariostart_savegame save(state_, preferences::save_compression_format());

				save.save_game_automatic(video_);
			}

		}
	}

	if (!state_.get_scenario_id().empty()) {
		std::string message = _("Unknown scenario: '$scenario|'");
		utils::string_map symbols;
		symbols["scenario"] = state_.get_scenario_id();
		message = utils::interpolate_variables_into_string(message, &symbols);
		gui2::show_error_message(video_, message);
		return LEVEL_RESULT::QUIT;
	}

	if (game_type == game_classification::CAMPAIGN_TYPE::SCENARIO){
		if (preferences::delete_saves()) {
			savegame::clean_saves(state_.classification().label);
		}
	}
	return LEVEL_RESULT::VICTORY;
}
예제 #3
0
void start_local_game_commandline(const config& game_config, saved_game& state, const commandline_options& cmdline_opts)
{
	DBG_MP << "starting local MP game from commandline" << std::endl;

	// The setup is done equivalently to lobby MP games using as much of existing
	// code as possible.  This means that some things are set up that are not
	// needed in commandline mode, but they are required by the functions called.
	preferences::set_message_private(false);

	DBG_MP << "entering create mode" << std::endl;

	// Set the default parameters
	state.clear(); // This creates these parameters with default values defined in mp_game_settings.cpp
	mp_game_settings& parameters = state.mp_settings();

	// Hardcoded default values
	parameters.mp_era = "era_default";
	parameters.name = "multiplayer_The_Freelands";

	// Default values for which at getter function exists
	parameters.num_turns = settings::get_turns("");
	parameters.village_gold = settings::get_village_gold("");
	parameters.village_support = settings::get_village_support("");
	parameters.xp_modifier = settings::get_xp_modifier("");

	// Do not use map settings if --ignore-map-settings commandline option is set
	if(cmdline_opts.multiplayer_ignore_map_settings) {
		DBG_MP << "ignoring map settings" << std::endl;
		parameters.use_map_settings = false;
	} else {
		parameters.use_map_settings = true;
	}

	// None of the other parameters need to be set, as their creation values above are good enough for CL mode.
	// In particular, we do not want to use the preferences values.

	state.classification().campaign_type = game_classification::CAMPAIGN_TYPE::MULTIPLAYER;

	// [era] define.
	if(cmdline_opts.multiplayer_era) {
		parameters.mp_era = *cmdline_opts.multiplayer_era;
	}

	if(const config& cfg_era = game_config.find_child("era", "id", parameters.mp_era)) {
		state.classification().era_define = cfg_era["define"].str();
	} else {
		std::cerr << "Could not find era '" << parameters.mp_era << "'\n";
		return;
	}

	// [multiplayer] define.
	if(cmdline_opts.multiplayer_scenario) {
		parameters.name = *cmdline_opts.multiplayer_scenario;
	}

	if(const config& cfg_multiplayer = game_config.find_child("multiplayer", "id", parameters.name)) {
		state.classification().scenario_define = cfg_multiplayer["define"].str();
	} else {
		std::cerr << "Could not find [multiplayer] '" << parameters.name << "'\n";
		return;
	}

	game_config_manager::get()->load_game_config_for_game(state.classification());
	state.set_carryover_sides_start(
		config {"next_scenario", parameters.name}
	);

	state.expand_random_scenario();
	state.expand_mp_events();
	state.expand_mp_options();

	// Should number of turns be determined from scenario data?
	if(parameters.use_map_settings && state.get_starting_pos()["turns"]) {
		DBG_MP << "setting turns from scenario data: " << state.get_starting_pos()["turns"] << std::endl;
		parameters.num_turns = state.get_starting_pos()["turns"];
	}

	DBG_MP << "entering connect mode" << std::endl;

	statistics::fresh_stats();

	{
		ng::connect_engine_ptr connect_engine(new ng::connect_engine(state, true, nullptr));

		// Update the parameters to reflect game start conditions
		connect_engine->start_game_commandline(cmdline_opts);
	}

	if(resources::recorder && cmdline_opts.multiplayer_label) {
		std::string label = *cmdline_opts.multiplayer_label;
		resources::recorder->add_log_data("ai_log","ai_label",label);
	}

	unsigned int repeat = (cmdline_opts.multiplayer_repeat) ? *cmdline_opts.multiplayer_repeat : 1;
	for(unsigned int i = 0; i < repeat; i++){
		saved_game state_copy(state);
		campaign_controller controller(state_copy, game_config, game_config_manager::get()->terrain_types());
		controller.play_game();
	}
}