From ef4ae1cf5d54cf168c9bd300d374899511071d32 Mon Sep 17 00:00:00 2001 From: gfgtdf Date: Tue, 12 Jun 2018 22:28:25 +0200 Subject: [PATCH] allow non hosts to change factions later. previously players had to leave an rejoin the game to change their faction. this was most annoying in coop games where you want might want to choose your faction in consultation with the other players. Also you previously could not even checkout the different available factions again after you joined the game. --- data/gui/window/mp_join_game.cfg | 12 ++++ src/gui/dialogs/multiplayer/mp_join_game.cpp | 72 ++++++++++++++++++++ src/gui/dialogs/multiplayer/mp_join_game.hpp | 2 + 3 files changed, 86 insertions(+) diff --git a/data/gui/window/mp_join_game.cfg b/data/gui/window/mp_join_game.cfg index 1574864d7475..34e4dee58e94 100644 --- a/data/gui/window/mp_join_game.cfg +++ b/data/gui/window/mp_join_game.cfg @@ -61,6 +61,18 @@ [/label] [/column] + [column] + grow_factor = 0 + vertical_alignment = "center" + + [button] + id = "select_leader" + definition = "settings_mp_staging" + tooltip = _"Select the faction and leader for this side" + [/button] + + [/column] + [column] grow_factor = 1 horizontal_grow = true diff --git a/src/gui/dialogs/multiplayer/mp_join_game.cpp b/src/gui/dialogs/multiplayer/mp_join_game.cpp index 8c2ee92707e7..20d7e90ce09d 100644 --- a/src/gui/dialogs/multiplayer/mp_join_game.cpp +++ b/src/gui/dialogs/multiplayer/mp_join_game.cpp @@ -154,6 +154,8 @@ bool mp_join_game::fetch_game_config() int side_num = 0, nb_sides = 0; for(const config& side : get_scenario().child_range("side")) { + // TODO: it can happen that the scenario specifies that the controller + // of a side should also gain control of another side. if(side["controller"] == "reserved" && side["current_player"] == preferences::login()) { side_choice = &side; side_num = nb_sides; @@ -188,6 +190,11 @@ bool mp_join_game::fetch_game_config() // If the client is allowed to choose their team, do that here instead of having it set by the server if((*side_choice)["allow_changes"].to_bool(true)) { + // TODO: show_flg_select does basicially the same, + // i didn't want to risk breakig this for stable (1.14) + // but id's be better if we didnt have this code dublication. + // what i am in particular unsure about is why the '!era' and + // 'possible_sides.empty()' cases below are handled differntly here. const config& era = level_.child("era"); // TODO: Check whether we have the era. If we don't, inform the player if(!era) { @@ -304,6 +311,59 @@ void mp_join_game::pre_show(window& window) plugins_context_->set_callback("chat", [&chat](const config& cfg) { chat.send_chat_message(cfg["message"], false); }, true); } +void mp_join_game::show_flg_select(int side_num) +{ + if(const config& side_choice = get_scenario().child("side", side_num - 1)) { + if(!side_choice["allow_changes"].to_bool(true)) { + return; + } + const config& era = level_.child("era"); + if(!era) { + ERR_MP << "no era information\n"; + return; + } + + config::const_child_itors possible_sides = era.child_range("multiplayer_side"); + if(possible_sides.empty()) { + WRN_MP << "no [multiplayer_side] found in era '" << era["id"] << "'.\n"; + return; + } + + const std::string color = side_choice["color"].str(); + + std::vector era_factions; + for(const config& side : possible_sides) { + era_factions.push_back(&side); + } + + const bool is_mp = state_.classification().is_normal_mp_game(); + const bool lock_settings = get_scenario()["force_lock_settings"].to_bool(!is_mp); + 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); + + gui2::dialogs::faction_select dlg(flg, color, side_num); + dlg.show(); + + if(dlg.get_retval() != gui2::retval::OK) { + 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(); + //TODO: the host cannot yet handle this and always uses the first side owned by that player. + change["side_num"] = side_num; + + network_connection_.send_data(faction); + } +} + void mp_join_game::generate_side_list(window& window) { if(stop_updates_) { @@ -318,7 +378,9 @@ void mp_join_game::generate_side_list(window& window) team_tree_map_.clear(); const std::map empty_map; + int side_num = 0; for(const auto& side : get_scenario().child_range("side")) { + ++side_num; if(!side["allow_player"].to_bool(true)) { continue; } @@ -411,6 +473,16 @@ void mp_join_game::generate_side_list(window& window) grid& row_grid = node.get_grid(); + auto* select_leader_button = find_widget