Ejemplo n.º 1
0
void synced_context::server_choice::send_request() const
{
	resources::controller->send_to_wesnothd(config_of
		("request_choice", config_of
			("request_id", resources::controller->get_server_request_number())
			(name(), request())
		)
	);
}
Ejemplo n.º 2
0
void tchatbox::send_chat_message(const std::string& message,
	bool /*allies_only*/)
{
	::config c = config_of("message", config_of("message", message)("sender", preferences::login()));
	add_chat_message(time(nullptr), preferences::login(), 0, message);

	if(wesnothd_connection_) {
		wesnothd_connection_->send_data(c);
	}
}
Ejemplo n.º 3
0
void tod_manager::update_server_information() const
{
	if(resources::controller->current_team().is_local()) {
		//the currently active side informs the mp server about the turn change.
		//NOTE: The current implementation does not guarnateee that the server gets informed
		// about those changes in 100% of cases. But that is ok because the information is only
		// used to display the turn limit in the lobby (as opposed to things that cause OOS).
		resources::controller->send_to_wesnothd(config_of
			("change_turns_wml", config_of
				("current", turn_)
				("max", num_turns_)
			)
		);
	}
}
Ejemplo n.º 4
0
void playturn_network_adapter::read_from_network()
{
	assert(!data_.empty());
	
	this->data_.push_back(config());
	config& back = data_.back();
	bool has_data = this->network_reader_(back);
	//ping is handeled by network.cpp and we can ignore it.
	back.remove_attribute("ping");
	if((!has_data) || back.empty())
	{
		this->data_.pop_back();
		return;
	}
	assert(!data_.back().empty());
	
	if(back.has_attribute("side_drop"))
	{
		config child;
		child["side_num"] = back["side_drop"];
		child["controller"] = back["controller"];
		this->data_.push_back(config_of("side_drop", child));
		back.remove_attribute("side_drop");
		back.remove_attribute("controller");
	}
	assert(!data_.back().empty());
	//there should be no attributes left.

	if(back.attribute_range().first != back.attribute_range().second )
	{
		ERR_NW << "found unexpected attribute:" <<back.debug() << "\n";
	}
}
Ejemplo n.º 5
0
void mp_staging::network_handler(window& window)
{
	// First, send off any changes if they've been accumulated
	if(state_changed_) {
		connect_engine_.update_and_send_diff();
	}

	// Next, check for any incoming changes
	config data;
	if(!state_changed_ && (!wesnothd_connection_ || !wesnothd_connection_->receive_data(data))) {
		return;
	}

	// Update chat
	find_widget<chatbox>(&window, "chat", false).process_network_data(data);

	// TODO: why is this needed...
	const bool was_able_to_start = connect_engine_.can_start_game();

	bool quit_signal_recieved;
	std::tie(quit_signal_recieved, std::ignore) = connect_engine_.process_network_data(data);

	if(quit_signal_recieved) {
		window.set_retval(window::CANCEL);
	}

	// Update side leader displays
	// This is basically only needed when a new player joins and selects their faction
	for(auto& tree_entry : side_tree_map_) {
		ng::side_engine_ptr side = tree_entry.first;

		grid& row_grid = tree_entry.second->get_grid();

		update_leader_display(side, row_grid);

		std::vector<config> controller_names;
		for(const auto& controller : side->controller_options()) {
			controller_names.push_back(config_of("label", controller.second));
		}

		menu_button& controller_selection = find_widget<menu_button>(&row_grid, "controller", false);

		controller_selection.set_values(controller_names, side->current_controller_index());
		controller_selection.set_active(controller_names.size() > 1);
	}

	// Update player list
	// TODO: optimally, it wouldn't regenerate the entire list every single refresh cycle
	update_player_list(window);

	// Update status label and buttons
	update_status_label_and_buttons(window);

	if(!was_able_to_start && connect_engine_.can_start_game()) {
		mp_ui_alerts::ready_for_start();
	}

	state_changed_ = false;
}
Ejemplo n.º 6
0
static config find_helper(const ng::create_engine * eng_ptr, const config & cfg)
{
	assert(eng_ptr);
	const ng::create_engine & eng = *eng_ptr;
	std::string str = cfg["id"].str();

	return config_of("index", eng.find_level_by_id(str))("type", eng.find_level_type_by_id(str));
}
Ejemplo n.º 7
0
void create_engine::prepare_for_scenario()
{
	DBG_MP << "preparing data for scenario by reloading game config\n";

	state_.classification().scenario_define =
		current_level().data()["define"].str();

	state_.set_carryover_sides_start(
		config_of("next_scenario", current_level().data()["id"])
	);
}
Ejemplo n.º 8
0
cave_map_generator::cave_map_generator_job::cave_map_generator_job(const cave_map_generator& pparams, boost::optional<uint32_t> randomseed)
	: params(pparams)
	, flipx_(false)
	, flipy_(false)
	, map_(t_translation::ter_map(params.width_ + 2 * gamemap::default_border, params.height_ + 2 * gamemap::default_border/*, params.wall_*/))
	, starting_positions_()
	, chamber_ids_()
	, chambers_()
	, passages_()
	, res_(params.cfg_.child_or_empty("settings"))
	, rng_() //initialises with rand()
{
	res_.add_child("event", config_of
		("name", "start")
		("message", config_of
			("message", "scenario_generation=cave is deprecated and will be removed soon.")
		)
	);
	uint32_t seed = randomseed.get_ptr() ? *randomseed.get_ptr() : seed_rng::next_seed();
	rng_.seed(seed);
	LOG_NG << "creating random cave with seed: " << seed << '\n';
	flipx_ = int(rng_() % 100) < params.flipx_chance_;
	flipy_ = int(rng_() % 100) < params.flipy_chance_;

	LOG_NG << "creating scenario....\n";
	generate_chambers();

	LOG_NG << "placing chambers...\n";
	for(std::vector<chamber>::const_iterator c = chambers_.begin(); c != chambers_.end(); ++c) {
		place_chamber(*c);
	}

	LOG_NG << "placing passages...\n";

	for(std::vector<passage>::const_iterator p = passages_.begin(); p != passages_.end(); ++p) {
		place_passage(*p);
	}
	LOG_NG << "outputting map....\n";

	res_["map_data"] = t_translation::write_game_map(map_, starting_positions_);
}
Ejemplo n.º 9
0
void game_launcher::set_tutorial()
{
	state_ = saved_game();
	state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::TUTORIAL;
	state_.classification().campaign_define = "TUTORIAL";
	state_.mp_settings().mp_era = "era_default";
	state_.mp_settings().show_connect = false;
	state_.set_carryover_sides_start(
		config_of("next_scenario", "tutorial")
	);

}
Ejemplo n.º 10
0
void playturn_network_adapter::read_from_network()
{
	assert(!data_.empty());

	this->data_.push_back(config());
	config& back = data_.back();
	bool has_data = false;
	try
	{
		has_data = this->network_reader_(back);
	}
	catch(...)
	{
		//Readin from network can throw, we want to ignore the possibly corrupt packet in this case.
		this->data_.pop_back();
		throw;
	}
	//ping is handeled by network.cpp and we can ignore it.
	back.remove_attribute("ping");
	if((!has_data) || back.empty())
	{
		this->data_.pop_back();
		return;
	}
	assert(!data_.back().empty());

	if(back.has_attribute("side_drop"))
	{
		config child;
		child["side_num"] = back["side_drop"];
		child["controller"] = back["controller"];
		this->data_.push_back(config_of("side_drop", child));
		back.remove_attribute("side_drop");
		back.remove_attribute("controller");
	}
	else if(!back.attribute_range().empty() )
	{
		ERR_NW << "found unexpected attribute:" <<back.debug() << std::endl;
		this->data_.pop_back();
		//ignore those here
	}
	assert(!data_.back().empty());
	//there should be no attributes left.
}
Ejemplo n.º 11
0
	void play_scenario::play()
	{
		// We have to first append a "event" that collects end poisition
		end_pos_.reset(new end_position_collector(current_time_++));
		end_position_collector* end = static_cast<end_position_collector*>(end_pos_.get());
		source_.add_event(end_pos_);

		source_.type_key(current_time_++, SDLK_COLON, SDLMod(KMOD_LSHIFT | KMOD_SHIFT) );
		source_.type_key(current_time_++, SDLK_q);
		source_.type_key(current_time_++, SDLK_EXCLAIM);
		source_.type_key(current_time_++, SDLK_RETURN);

		saved_game& state = end->get_state();
		state.classification().campaign_type = game_classification::TEST;
		state.set_carryover_sides_start(
			config_of("next_scenario", id_)
		);
		play_game(get_fake_display(1024, 768), state, game_config_, tdata_);
	}
Ejemplo n.º 12
0
void set_scontext_synced::do_final_checkup(bool dont_throw)
{
	assert(!did_final_checkup_);
	std::stringstream msg;
	config co;
	config cn = config_of
		("random_calls", new_rng_->get_random_calls())
		("next_unit_id", resources::gameboard->unit_id_manager().get_save_id() + 1);
	if(checkup_instance->local_checkup(cn, co))
	{
		return;
	}
	if(co["random_calls"].empty())
	{
		msg << "cannot find random_calls check in replay" << std::endl;
	}
	else if(co["random_calls"] != cn["random_calls"])
	{
		msg << "We called random " << new_rng_->get_random_calls() << " times, but the original game called random " << co["random_calls"].to_int() << " times." << std::endl;
	}
	//Ignore empty next_unit_id to prevent false positives with older saves.
	if(!co["next_unit_id"].empty() && co["next_unit_id"] != cn["next_unit_id"])
	{
		msg << "Our next unit id is " << cn["next_unit_id"].to_int() << " but during the original the next unit id was " << co["next_unit_id"].to_int() << std::endl;
	}
	if(!msg.str().empty())
	{
		msg << co.debug() << std::endl;
		if(dont_throw)
		{
			ERR_REPLAY << msg.str() << std::flush;
		}
		else
		{
			replay::process_error(msg.str());
		}
	}
	did_final_checkup_ = true;
}
Ejemplo n.º 13
0
bool game_launcher::play_test()
{
	static bool first_time = true;

	if(!cmdline_opts_.test) {
		return true;
	}
	if(!first_time)
		return false;

	first_time = false;

	state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::TEST;
	state_.classification().campaign_define = "TEST";

	state_.mp_settings().mp_era = "era_default";
	state_.mp_settings().show_connect = false;

	state_.set_carryover_sides_start(
		config_of("next_scenario", test_scenario_)
	);



	game_config_manager::get()->
		load_game_config_for_game(state_.classification());

	try {
		campaign_controller ccontroller(video(), state_, game_config_manager::get()->game_config(), game_config_manager::get()->terrain_types());
		ccontroller.play_game();
	} catch (savegame::load_game_exception &e) {
		load_data_.reset(new savegame::load_game_metadata(std::move(e.data_)));
		return true;
	}

	return false;
}
Ejemplo n.º 14
0
void create_engine::prepare_for_campaign(const std::string& difficulty)
{
	DBG_MP << "preparing data for campaign by reloading game config\n";

	if (difficulty != "") {
		state_.classification().difficulty = difficulty;
	}

	state_.classification().campaign = current_level().data()["id"].str();
	state_.classification().abbrev = current_level().data()["abbrev"].str();

	state_.classification().end_text = current_level().data()["end_text"].str();
	state_.classification().end_text_duration =
		current_level().data()["end_text_duration"];

	state_.classification().campaign_define =
		current_level().data()["define"].str();
	state_.classification().campaign_xtra_defines =
		utils::split(current_level().data()["extra_defines"]);

	state_.set_carryover_sides_start(
		config_of("next_scenario", current_level().data()["first_scenario"])
	);
}
Ejemplo n.º 15
0
bool enter_create_mode(game_display& disp, const config& game_config,
	saved_game& state, jump_to_campaign_info jump_to_campaign, bool local_players_only) {

	bool configure_canceled = false;

	do {

		ng::create_engine create_eng(disp, state);
		create_eng.set_current_level_type(ng::level::TYPE::SP_CAMPAIGN);

		std::vector<ng::create_engine::level_ptr> campaigns(
			create_eng.get_levels_by_type_unfiltered(ng::level::TYPE::SP_CAMPAIGN));
		
		if (campaigns.empty()) {
		  gui2::show_error_message(disp.video(),
					  _("No campaigns are available.\n"));
			return false;
		}

		bool use_deterministic_mode = false;
		// No campaign selected from command line
		if (jump_to_campaign.campaign_id_.empty() == true)
		{
			gui2::tcampaign_selection dlg(create_eng);

			try {
				dlg.show(disp.video());
			} catch(twml_exception& e) {
				e.show(disp);
				return false;
			}

			if(dlg.get_retval() != gui2::twindow::OK) {
				return false;
			}

			use_deterministic_mode = dlg.get_deterministic();

		}
		else
		{
			// don't reset the campaign_id_ so we can know
			// if we should quit the game or return to the main menu

			// checking for valid campaign name
			bool not_found = true;
			for(size_t i = 0; i < campaigns.size(); ++i)
			{
				if (campaigns[i]->data()["id"] == jump_to_campaign.campaign_id_)
				{
					create_eng.set_current_level(i);
					not_found = false;
					break;
				}

			}

			// didn't find any campaign with that id
			if (not_found)
			{
				//TODO: use ERR_NG or similar
				std::cerr<<"No such campaign id to jump to: ["<<jump_to_campaign.campaign_id_<<"]\n";
				return false;
			}

		}

		std::string random_mode = use_deterministic_mode ? "deterministic" : "";
		state.classification().random_mode = random_mode;

		std::string selected_difficulty = create_eng.select_campaign_difficulty(jump_to_campaign.difficulty_);

		if (selected_difficulty == "FAIL") return false;
		if (selected_difficulty == "CANCEL") {
			if (jump_to_campaign.campaign_id_.empty() == false)
			{
				jump_to_campaign.campaign_id_ = "";
			}
			// canceled difficulty dialog, relaunch the campaign selection dialog
			return enter_create_mode(disp, game_config, state, jump_to_campaign, local_players_only);
		}

		create_eng.prepare_for_era_and_mods();
		create_eng.prepare_for_campaign(selected_difficulty);

		if(!jump_to_campaign.scenario_id_.empty()) {
			state.set_carryover_sides_start(
				config_of("next_scenario", jump_to_campaign.scenario_id_)
			);
		}
		create_eng.prepare_for_new_level();

		create_eng.get_parameters();
		if(!state.valid())
		{
			//TODO: use ERR_NG or similar
			std::cerr << "Cannot load scenario with id=" << state.get_scenario_id() << "\n";
			return false;
		}
		configure_canceled = !enter_configure_mode(disp, game_config_manager::get()->game_config(), state, local_players_only);

	} while (configure_canceled);

	return true;
}
Ejemplo n.º 16
0
bool enter_create_mode(CVideo& video, const config& game_config, saved_game& state, jump_to_campaign_info jump_to_campaign, bool local_players_only)
{
	bool configure_canceled = false;

	do {
		ng::create_engine create_eng(video, state);

		create_eng.set_current_level_type(ng::level::TYPE::SP_CAMPAIGN);

		const std::vector<ng::create_engine::level_ptr> campaigns =
			create_eng.get_levels_by_type_unfiltered(ng::level::TYPE::SP_CAMPAIGN);

		if(campaigns.empty()) {
			gui2::show_error_message(video, _("No campaigns are available."));
			return false;
		}

		std::string random_mode = "";

		// No campaign selected from command line
		if(jump_to_campaign.campaign_id_.empty()) {
			gui2::tcampaign_selection dlg(create_eng);

			try {
				dlg.show(video);
			} catch(twml_exception& e) {
				e.show(video);
				return false;
			}

			if(dlg.get_retval() != gui2::twindow::OK) {
				return false;
			}

			if(dlg.get_deterministic()) {
				random_mode = "deterministic";
			}
		} else {
			// Don't reset the campaign_id_ so we can know
			// if we should quit the game or return to the main menu

			// Checking for valid campaign name
			const auto campaign = std::find_if(campaigns.begin(), campaigns.end(), [&jump_to_campaign](ng::create_engine::level_ptr level) {
				return level->data()["id"] == jump_to_campaign.campaign_id_;
			});

			// Didn't find a campaign with that id
			if(campaign == campaigns.end()) {
				ERR_NG << "No such campaign id to jump to: [" << jump_to_campaign.campaign_id_ << "]" << std::endl;
				return false;
			}

			create_eng.set_current_level(campaign - campaigns.begin());
		}

		state.classification().random_mode = random_mode;

		const std::string selected_difficulty = create_eng.select_campaign_difficulty(jump_to_campaign.difficulty_);

		if(selected_difficulty == "FAIL") return false;
		if(selected_difficulty == "CANCEL") {
			if(!jump_to_campaign.campaign_id_.empty()) {
				jump_to_campaign.campaign_id_ = "";
			}

			// Canceled difficulty dialog, relaunch the campaign selection dialog
			return enter_create_mode(video, game_config, state, jump_to_campaign, local_players_only);
		}

		create_eng.prepare_for_era_and_mods();
		create_eng.prepare_for_campaign(selected_difficulty);

		if(!jump_to_campaign.scenario_id_.empty()) {
			state.set_carryover_sides_start(
				config_of("next_scenario", jump_to_campaign.scenario_id_)
			);
		}

		if(!state.valid()) {
			ERR_NG << "Cannot load scenario with id=" << state.get_scenario_id() << std::endl;
			return false;
		}

		configure_canceled = !enter_configure_mode(video, game_config_manager::get()->game_config(), state, create_eng, local_players_only);

	} while (configure_canceled);

	return true;
}
Ejemplo n.º 17
0
void mp_staging::add_side_node(window& window, ng::side_engine_ptr side)
{
	tree_view& tree = find_widget<tree_view>(&window, "side_list", false);
	static const std::map<std::string, string_map> empty_map;

	std::map<std::string, string_map> data;
	string_map item;

	item["label"] = std::to_string(side->index() + 1);
	data.emplace("side_number", item);

	// TODO: don't hardcode meganta?
	item["label"] = "units/unknown-unit.png~RC(magenta>" + std::to_string(side->color() + 1) + ")";
	data.emplace("leader_image", item);

	item["label"] = "icons/icon-random.png";
	data.emplace("leader_gender", item);

	// Check to see whether we've added a toplevel tree node for this team. If not, add one
	if(team_tree_map_.find(side->team_name()) == team_tree_map_.end()) {
		std::map<std::string, string_map> data;
		string_map item;

		item["label"] = (formatter() << _("Team:") << " " << side->user_team_name()).str();
		data.emplace("tree_view_node_label", item);

		tree_view_node& team_node = tree.add_node("team_header", data);
		team_node.add_sibling("side_spacer", empty_map);

		team_tree_map_[side->team_name()] = &team_node;
	}

	tree_view_node& node = team_tree_map_[side->team_name()]->add_child("side_panel", data);

	side_tree_map_[side] = &node;

	grid& row_grid = node.get_grid();

	update_leader_display(side, row_grid);

	// Status variables
	const bool fls = connect_engine_.force_lock_settings();
	const bool ums = connect_engine_.params().use_map_settings;

	const bool lock_gold   = side->cfg()["gold_lock"].to_bool(fls);
	const bool lock_income = side->cfg()["income_lock"].to_bool(fls);
	const bool lock_team   = side->cfg()["team_lock"].to_bool(fls);
	const bool lock_color  = side->cfg()["color_lock"].to_bool(fls);

	const bool saved_game = connect_engine_.params().saved_game;

	//
	// AI Algorithm
	//
	int selection = 0;

	// We use an index-based loop in order to get the index of the selected option
	std::vector<config> ai_options;
	for(unsigned i = 0; i < ai_algorithms_.size(); i++) {
		ai_options.push_back(config_of("label", ai_algorithms_[i]->text));

		if(ai_algorithms_[i]->id == side->ai_algorithm()) {
			selection = i;
		}
	}

	menu_button& ai_selection = find_widget<menu_button>(&row_grid, "ai_controller", false);

	ai_selection.set_values(ai_options, selection);
	ai_selection.connect_click_handler(std::bind(&mp_staging::on_ai_select, this, side, std::ref(ai_selection)));

	on_ai_select(side, ai_selection);

	//
	// Controller
	//
	std::vector<config> controller_names;
	for(const auto& controller : side->controller_options()) {
		controller_names.push_back(config_of("label", controller.second));
	}

	menu_button& controller_selection = find_widget<menu_button>(&row_grid, "controller", false);

	controller_selection.set_values(controller_names, side->current_controller_index());
	controller_selection.set_active(controller_names.size() > 1);
	controller_selection.connect_click_handler(std::bind(&mp_staging::on_controller_select, this, side, std::ref(row_grid)));

	on_controller_select(side, row_grid);

	//
	// Leader controls
	//
	button& leader_select = find_widget<button>(&row_grid, "select_leader", false);

	leader_select.set_active(!saved_game);

	connect_signal_mouse_left_click(leader_select,
		std::bind(&mp_staging::select_leader_callback, this, std::ref(window), side, std::ref(row_grid)));

	//
	// Team
	//
	std::vector<config> team_names;
	for(const auto& team : side->player_teams()) {
		team_names.push_back(config_of("label", team));
	}

	menu_button& team_selection = find_widget<menu_button>(&row_grid, "side_team", false);

	// HACK: side->team() does not get its index from side->player_teams(), but rather side->team_names().
	// As such, the index is off if there is only 1 playable team. This is a hack to make sure the menu_button
	// widget doesn't assert with the invalid initial selection. The connect_engine should be fixed once the GUI1
	// dialog is dropped
	team_selection.set_values(team_names, std::min<int>(team_names.size() - 1, side->team()));
	team_selection.set_active(!saved_game);
	team_selection.connect_click_handler(std::bind(&mp_staging::on_team_select, this, std::ref(window), side, std::ref(team_selection), _3, _4));

	//
	// Colors
	//
	std::vector<config> color_options;
	for(const auto& color : side->color_options()) {
		color_options.push_back(config_of
			("label", font::get_color_string_pango(color))
			("icon", (formatter() << "misc/status.png~RC(magenta>" << color << ")").str())
		);
	}

	menu_button& color_selection = find_widget<menu_button>(&row_grid, "side_color", false);

	color_selection.set_values(color_options, side->color());
	color_selection.set_active(!saved_game);
	color_selection.set_use_markup(true);
	color_selection.connect_click_handler(std::bind(&mp_staging::on_color_select, this, side, std::ref(row_grid)));

	//
	// Gold and Income
	//
	slider& slider_gold = find_widget<slider>(&row_grid, "side_gold_slider", false);
	slider_gold.set_value(side->cfg()["gold"].to_int(100));

	connect_signal_notify_modified(slider_gold, std::bind(
		&mp_staging::on_side_slider_change<&ng::side_engine::set_gold>, this, side, std::ref(slider_gold)));

	slider& slider_income = find_widget<slider>(&row_grid, "side_income_slider", false);
	slider_income.set_value(side->cfg()["income"]);

	connect_signal_notify_modified(slider_income, std::bind(
		&mp_staging::on_side_slider_change<&ng::side_engine::set_income>, this, side, std::ref(slider_income)));

	// TODO: maybe display the saved values
	if(saved_game) {
		slider_gold.set_visible(widget::visibility::invisible);
		slider_income.set_visible(widget::visibility::invisible);
	}

	//
	// Gold, income, team, and color are only suggestions unless explicitly locked
	//
	if(!saved_game && ums) {
		team_selection.set_active(!lock_team);
		color_selection.set_active(!lock_color);

		slider_gold.set_active(!lock_gold);
		slider_income.set_active(!lock_income);
	}
}
Ejemplo n.º 18
0
void plugins_context::set_accessor_int(const std::string & name, std::function<int(config)> func)
{
	set_accessor(name, [func, name](const config& cfg) { return config_of(name, func(cfg)); });
}
Ejemplo n.º 19
0
LEVEL_RESULT playsingle_controller::play_scenario(const config& level)
{
	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(!this->is_skipping_replay()) {
		show_story(gui_->video(), get_scenario_name(), level.child_range("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;
		}
	}
	LOG_NG << "entering try... " << (SDL_GetTicks() - ticks()) << "\n";
	try {
		play_scenario_init();
		// clears level config;
		this->saved_game_.remove_snapshot();

		if (!is_regular_game_end() && !linger_) {
			play_scenario_main_loop();
		}
		if (game_config::exit_at_end) {
			exit(0);
		}
		const bool is_victory = get_end_level_data_const().is_victory;

		if(gamestate().gamedata_.phase() <= game_data::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();

		const end_level_data& end_level = get_end_level_data_const();
		if (!end_level.transient.custom_endlevel_music.empty()) {
			if (!is_victory) {
				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 LEVEL_RESULT::VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event
		}
		if(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 LEVEL_RESULT::VICTORY;
		}
		pump().fire(is_victory ? "victory" : "defeat");
		{ // Block for set_scontext_synced_base
			set_scontext_synced_base sync;
			pump().fire("scenario end");
		}
		if(end_level.proceed_to_next_level) {
			gamestate().board_.heal_all_survivors();
		}
		if(is_observer()) {
			gui2::show_transient_message(gui_->video(), _("Game Over"), _("The game is over."));
			return LEVEL_RESULT::OBSERVER_END;
		}
		// 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.
		network::send_data(config_of
			("info", config_of
				("type", "termination")
				("condition", "game over")
				("result", is_victory ? "victory" : "defeat")
			));
		// 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.
		const std::string& end_music = is_victory ? select_victory_music() : select_defeat_music();
		if(end_music.empty() != true) {
			sound::play_music_once(end_music);
		}
		persist_.end_transaction();
		return is_victory ? LEVEL_RESULT::VICTORY : LEVEL_RESULT::DEFEAT;
	} 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;
		}

		scoped_savegame_snapshot snapshot(*this);
		savegame::ingame_savegame save(saved_game_, *gui_, 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 LEVEL_RESULT::QUIT;
		}
	}

	return LEVEL_RESULT::QUIT;
}
Ejemplo n.º 20
0
void tmp_create_game::post_show(twindow& window)
{
	if(get_retval() == twindow::OK) {
		create_engine_.prepare_for_era_and_mods();

		if(create_engine_.current_level_type() == ng::level::TYPE::CAMPAIGN ||
			create_engine_.current_level_type() == ng::level::TYPE::SP_CAMPAIGN) {
			create_engine_.prepare_for_campaign();
		} else if(create_engine_.current_level_type() == ng::level::TYPE::SCENARIO) {
			create_engine_.prepare_for_scenario();
		} else {
			// This means define= doesn't work for randomly generated scenarios
			create_engine_.prepare_for_other();
		}

		create_engine_.prepare_for_new_level();

		create_engine_.get_parameters();

		config_engine_->set_use_map_settings(use_map_settings_->get_widget_value(window));

		if(!config_engine_->force_lock_settings()) {
			config_engine_->set_num_turns(turns_->get_widget_value(window));
			config_engine_->set_village_gold(gold_->get_widget_value(window));
			config_engine_->set_village_support(support_->get_widget_value(window));
			config_engine_->set_xp_modifier(experience_->get_widget_value(window));
			config_engine_->set_random_start_time(start_time_->get_widget_value(window));
			config_engine_->set_fog_game(fog_->get_widget_value(window));
			config_engine_->set_shroud_game(shroud_->get_widget_value(window));
			config_engine_->write_parameters();
		}

		config_engine_->set_mp_countdown(time_limit_->get_widget_value(window));
		config_engine_->set_mp_countdown_init_time(init_turn_limit->get_widget_value(window));
		config_engine_->set_mp_countdown_turn_bonus(turn_bonus_->get_widget_value(window));
		config_engine_->set_mp_countdown_reservoir_time(reservior_->get_widget_value(window));
		config_engine_->set_mp_countdown_action_bonus(action_bonus_->get_widget_value(window));

		config_engine_->set_allow_observers(observers_->get_widget_value(window));
		config_engine_->set_registered_users_only(registered_users_->get_widget_value(window));
		config_engine_->set_oos_debug(strict_sync_->get_widget_value(window));
		config_engine_->set_shuffle_sides(shuffle_sides_->get_widget_value(window));

		// TODO: we rely on a hardcoded list in the WML file. Should we procedurally generate the contents?
		config_engine_->set_random_faction_mode(mp_game_settings::RANDOM_FACTION_MODE::from_int(
			find_widget<tcombobox>(&window, "random_faction_mode", false).get_value()));

		config options;
		for(const auto& mod_pair : visible_options_) {
			config& mod = options.add_child(mod_pair.first[0]);
			mod["id"] = mod_pair.first[1];
			for(const auto& pair : mod_pair.second) {
				//TODO: change this to some key=value format as soon as we drop the old  mp configure screen.
				mod.add_child("option", config_of("id", pair.first)("value", pair.second()));
			}
		}

		config_engine_->set_options(options);

		// Set game name
		const std::string name = find_widget<ttext_box>(&window, "game_name", false).get_value();
		if(!name.empty() && (name != config_engine_->game_name_default())) {
			config_engine_->set_game_name(name);
		}

		// Set game password
		const std::string password = find_widget<ttext_box>(&window, "game_password", false).get_value();
		if(!password.empty()) {
			config_engine_->set_game_password(password);
		}
	}
}
Ejemplo n.º 21
0
// Same as play_test except that we return the results of play_game.
int game_launcher::unit_test()
{
	static bool first_time_unit = true;

	if(!cmdline_opts_.unit_test) {
		return 0;
	}
	if(!first_time_unit)
		return 0;

	first_time_unit = false;

	state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::TEST;
	state_.classification().campaign_define = "TEST";
	state_.set_carryover_sides_start(
		config_of("next_scenario", test_scenario_)
	);


	game_config_manager::get()->
		load_game_config_for_game(state_.classification());

	try {
		campaign_controller ccontroller(video(), state_, game_config_manager::get()->game_config(), game_config_manager::get()->terrain_types(), true);
		LEVEL_RESULT res = ccontroller.play_game();
		if (!(res == LEVEL_RESULT::VICTORY) || lg::broke_strict()) {
			return 1;
		}
	} catch(wml_exception& e) {
		std::cerr << "Caught WML Exception:" << e.dev_message << std::endl;
		return 1;
	}

	savegame::clean_saves(state_.classification().label);

	if (cmdline_opts_.noreplaycheck)
		return 0; //we passed, huzzah!

	savegame::replay_savegame save(state_, compression::NONE);
	save.save_game_automatic(video(), false, "unit_test_replay"); //false means don't check for overwrite

	load_data_.reset(new savegame::load_game_metadata{ "unit_test_replay" , "", true, true, false });

	if (!load_game()) {
		std::cerr << "Failed to load the replay!" << std::endl;
		return 3; //failed to load replay
	}

	try {
		campaign_controller ccontroller(video(), state_, game_config_manager::get()->game_config(), game_config_manager::get()->terrain_types(), true);
		LEVEL_RESULT res = ccontroller.play_replay();
		if (!(res == LEVEL_RESULT::VICTORY)) {
			std::cerr << "Observed failure on replay" << std::endl;
			return 4;
		}
	} catch(wml_exception& e) {
		std::cerr << "WML Exception while playing replay: " << e.dev_message << std::endl;
		return 4; //failed with an error during the replay
	}

	return 0; //we passed, huzzah!
}