Example #1
0
void wait::join_game(bool observe)
{
	//if we have got valid side data
	//the first condition is to make sure that we don't have another
	//WML message with a side-tag in it
	while (!level_.has_attribute("version") || !level_.child("side")) {
		network::connection data_res = dialogs::network_receive_dialog(disp(),
				_("Getting game data..."), level_);
		if (!data_res) {
			set_result(QUIT);
			return;
		}
		check_response(data_res, level_);
		if(level_.child("leave_game")) {
			set_result(QUIT);
			return;
		}
	}

	// Add the map name to the title.
	append_to_title(": " + level_["name"].t_str());

	if (!observe) {
		//search for an appropriate vacant slot. If a description is set
		//(i.e. we're loading from a saved game), then prefer to get the side
		//with the same description as our login. Otherwise just choose the first
		//available side.
		const config *side_choice = NULL;
		int side_num = -1, nb_sides = 0;
		foreach (const config &sd, level_.child_range("side"))
		{
			if (sd["controller"] == "reserved" && sd["current_player"] == preferences::login())
			{
				side_choice = &sd;
				side_num = nb_sides;
				break;
			}
			if (sd["controller"] == "network" && sd["player_id"].empty())
			{
				if (!side_choice) { // found the first empty side
					side_choice = &sd;
					side_num = nb_sides;
				}
				if (sd["current_player"] == preferences::login()) {
					side_choice = &sd;
					side_num = nb_sides;
					break;  // found the preferred one
				}
			}
			++nb_sides;
		}
		if (!side_choice) {
			set_result(QUIT);
			return;
		}

		bool allow_changes = (*side_choice)["allow_changes"].to_bool(true);

		//if the client is allowed to choose their team, instead of having
		//it set by the server, do that here.
		std::string leader_choice, gender_choice;

		if(allow_changes) {
			events::event_context context;

			const config &era = level_.child("era");
			/** @todo Check whether we have the era. If we don't inform the user. */
			if (!era)
				throw config::error(_("No era information found."));
			config::const_child_itors possible_sides = era.child_range("multiplayer_side");
			if (possible_sides.first == possible_sides.second) {
				set_result(QUIT);
				throw config::error(_("No multiplayer sides found"));
				return;
			}

			int color = side_num;
			const std::string color_str = (*side_choice)["color"];
			if (!color_str.empty())
				color = game_config::color_info(color_str).index() - 1;

			std::vector<const config *> leader_sides;
			foreach (const config &side, possible_sides) {
				leader_sides.push_back(&side);
			}

			int forced_faction = find_suitable_faction(leader_sides, *side_choice);
			if (forced_faction >= 0) {
				const config *f = leader_sides[forced_faction];
				leader_sides.clear();
				leader_sides.push_back(f);
			}

			std::vector<std::string> choices;
			foreach (const config *s, leader_sides)
			{
				const config &side = *s;
				const std::string &name = side["name"];
				const std::string &icon = side["image"];

				if (!icon.empty()) {
					std::string rgb = side["flag_rgb"];
					if (rgb.empty())
						rgb = "magenta";

					choices.push_back(IMAGE_PREFIX + icon + "~RC(" + rgb + ">" +
						lexical_cast<std::string>(color+1) + ")" + COLUMN_SEPARATOR + name);
				} else {
					choices.push_back(name);
				}
			}

			std::vector<gui::preview_pane* > preview_panes;
			leader_preview_pane leader_selector(disp(), leader_sides, color);
			preview_panes.push_back(&leader_selector);

			const int res = gui::show_dialog(disp(), NULL, _("Choose your faction:"), _("Starting position: ") + lexical_cast<std::string>(side_num + 1),
						gui::OK_CANCEL, &choices, &preview_panes);
			if(res < 0) {
				set_result(QUIT);
				return;
			}
			const int faction_choice = res;
			leader_choice = leader_selector.get_selected_leader();
			gender_choice = leader_selector.get_selected_gender();

			assert(static_cast<unsigned>(faction_choice) < leader_sides.size());

			config faction;
			config& change = faction.add_child("change_faction");
			change["name"] = preferences::login();
			change["faction"] = forced_faction >= 0 ? forced_faction : faction_choice;
			change["leader"] = leader_choice;
			change["gender"] = gender_choice;
			network::send_data(faction, 0);
		}

	}
Example #2
0
void wait::join_game(bool observe)
{
	const bool download_res = download_level_data();
	if (!download_res) {
		DBG_MP << "mp wait: could not download level data, quitting...";
		set_result(QUIT);
		return;
	} else if (!get_scenario()["allow_new_game"].to_bool(true) && !level_.child_or_empty("multiplayer")["savegame"].to_bool(false)) {
		set_result(PLAY);
		return;
	}

	if (first_scenario_) {
		state_ = saved_game();
		state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::MULTIPLAYER;

		const config* campaign = &game_config_manager::get()->
			game_config().find_child("campaign", "id",
				level_.child("multiplayer")["mp_campaign"]);

		const config* scenario = &game_config_manager::get()->
			game_config().find_child("multiplayer", "id",
				level_.child(lexical_cast<std::string>(game_classification::CAMPAIGN_TYPE::MULTIPLAYER))["id"]);

		const config* era = &game_config_manager::get()->
			game_config().find_child("era", "id", level_.child("era")["id"]);

		if (*campaign) {
			state_.classification().difficulty =
				level_.child("multiplayer")["difficulty_define"].str();
			state_.classification().campaign_define =
				(*campaign)["define"].str();
			state_.classification().campaign_xtra_defines =
				utils::split((*campaign)["extra_defines"]);
		}

		if (*scenario)
			state_.classification().scenario_define =
				(*scenario)["define"].str();

		if (*era)
			state_.classification().era_define =
				(*era)["define"].str();

		BOOST_FOREACH(const config& mod, level_.child_range("modification")) {
			const config* modification = &game_config_manager::get()->
				game_config().find_child("modification", "id", mod["id"]);
			if (*modification) {
				state_.classification().mod_defines.push_back(
					(*modification)["define"].str());
			}
		}


		// Make sure that we have the same config as host, if possible.
		game_config_manager::get()->
			load_game_config_for_game(state_.classification());
	}

	// Add the map name to the title.
	append_to_title(": " + get_scenario()["name"].t_str());

	if (!observe) {
		//search for an appropriate vacant slot. If a description is set
		//(i.e. we're loading from a saved game), then prefer to get the side
		//with the same description as our login. Otherwise just choose the first
		//available side.
		const config *side_choice = NULL;
		int side_num = -1, nb_sides = 0;
		BOOST_FOREACH(const config &sd, get_scenario().child_range("side"))
		{
			DBG_MP << "*** side " << nb_sides << "***\n" << sd.debug() << "***\n";

			if (sd["controller"] == "reserved" && sd["current_player"] == preferences::login())
			{
				side_choice = &sd;
				side_num = nb_sides;
				break;
			}
			if (sd["controller"] == "network" && sd["player_id"].empty())
			{
				if (!side_choice) { // found the first empty side
					side_choice = &sd;
					side_num = nb_sides;
				}
				if (sd["current_player"] == preferences::login()) {
					side_choice = &sd;
					side_num = nb_sides;
					break;  // found the preferred one
				}
			}
			++nb_sides;
		}
		if (!side_choice) {
			size_t count = 0;
			for(config::child_itors its = get_scenario().child_range("side"); its.second != its.first; ++its.first) {
				++count;
			}
			DBG_MP << "could not find a side, all " << count << " sides were unsuitable\n";
			set_result(QUIT);
			return;
		}

		bool allow_changes = (*side_choice)["allow_changes"].to_bool(true);

		//if the client is allowed to choose their team, instead of having
		//it set by the server, do that here.
		if(allow_changes) {
			events::event_context context;

			const config &era = level_.child("era");
			/** @todo Check whether we have the era. If we don't inform the user. */
			if (!era)
				throw config::error(_("No era information found."));
			config::const_child_itors possible_sides = era.child_range("multiplayer_side");
			if (possible_sides.first == possible_sides.second) {
				set_result(QUIT);
				throw config::error(_("No multiplayer sides found"));
			}

			int color = side_num;
			const std::string color_str = (*side_choice)["color"];
			if (!color_str.empty())
				color = game_config::color_info(color_str).index() - 1;

			std::vector<const config*> era_factions;
			BOOST_FOREACH(const config &side, possible_sides) {
				era_factions.push_back(&side);
			}

			const bool lock_settings =
				get_scenario()["force_lock_settings"].to_bool();
			const bool use_map_settings =
				level_.child("multiplayer")["mp_use_map_settings"].to_bool();
			const bool saved_game =
				level_.child("multiplayer")["savegame"].to_bool();

			ng::flg_manager flg(era_factions, *side_choice, lock_settings, use_map_settings,
				saved_game, color);

			std::vector<std::string> choices;
			BOOST_FOREACH(const config *s, flg.choosable_factions())
			{
				const config &side = *s;
				const std::string &name = side["name"];
				const std::string &icon = side["image"];

				if (!icon.empty()) {
					std::string rgb = side["flag_rgb"];
					if (rgb.empty())
						rgb = "magenta";

					choices.push_back(IMAGE_PREFIX + icon + "~RC(" + rgb + ">" +
						lexical_cast<std::string>(color+1) + ")" + COLUMN_SEPARATOR + name);
				} else {
					choices.push_back(name);
				}
			}

			std::vector<gui::preview_pane* > preview_panes;
			leader_preview_pane leader_selector(disp(), flg, color);
			preview_panes.push_back(&leader_selector);

			const int faction_choice = gui::show_dialog(disp(), NULL,
				_("Choose your faction:"), _("Starting position: ") +
				lexical_cast<std::string>(side_num + 1), gui::OK_CANCEL,
				&choices, &preview_panes);
			if(faction_choice < 0) {
				set_result(QUIT);
				return;
			}

			config faction;
			config& change = faction.add_child("change_faction");
			change["change_faction"] = true;
			change["name"] = preferences::login();
			change["faction"] = flg.current_faction()["id"];
			change["leader"] = flg.current_leader();
			change["gender"] = flg.current_gender();
			network::send_data(faction, 0);
		}

	}