15 #define GETTEXT_DOMAIN "wesnoth-lib" 48 #include <boost/algorithm/string.hpp> 52 #define DBG_MP LOG_STREAM(debug, log_mp_create) 53 #define WRN_MP LOG_STREAM(warn, log_mp_create) 54 #define ERR_MP LOG_STREAM(err, log_mp_create) 68 : create_engine_(state)
71 , selected_game_index_(-1)
72 , selected_rfm_index_(-1)
82 , strict_sync_(register_bool("strict_sync", true))
83 , private_replay_(register_bool("private_replay", true))
94 , local_mode_(local_mode)
98 {ng::level::TYPE::CAMPAIGN,
_(
"Multiplayer Campaigns")},
99 {ng::level::TYPE::SP_CAMPAIGN,
_(
"Singleplayer Campaigns")},
100 {ng::level::TYPE::USER_MAP,
_(
"Custom Maps")},
101 {ng::level::TYPE::USER_SCENARIO,
_(
"Custom Scenarios")},
102 {ng::level::TYPE::RANDOM_MAP,
_(
"Random Maps")},
105 level_types_.erase(std::remove_if(level_types_.begin(), level_types_.end(),
107 return create_engine_.get_levels_by_type_unfiltered(type_info.first).empty();
108 }), level_types_.end());
111 mp_game_settings::RANDOM_FACTION_MODE::DEFAULT,
112 mp_game_settings::RANDOM_FACTION_MODE::NO_MIRROR,
113 mp_game_settings::RANDOM_FACTION_MODE::NO_ALLY_MIRROR,
116 set_show_even_without_video(
true);
118 create_engine_.init_active_mods();
120 create_engine_.get_state().clear();
121 create_engine_.get_state().classification().campaign_type = game_classification::CAMPAIGN_TYPE::MULTIPLAYER;
124 set_allow_plugin_skip(
false);
132 find_widget<button>(&win,
"random_map_regenerate",
false),
136 find_widget<button>(&win,
"random_map_settings",
false),
140 find_widget<button>(&win,
"load_game",
false),
155 std::bind(&mp_create_game::on_filter_change<slider>,
this,
"num_players",
true));
157 text_box& filter = find_widget<text_box>(&win,
"game_filter",
false);
160 std::bind(&mp_create_game::on_filter_change<text_box>,
this,
"game_filter",
true));
163 win.keyboard_capture(&filter);
168 std::vector<config> game_types;
170 game_types.emplace_back(
"label", type_info.second);
173 if(game_types.empty()) {
178 menu_button& game_menu_button = find_widget<menu_button>(&win,
"game_types",
false);
181 auto get_initial_type_index = [
this]()->
int {
186 if(
index != level_types_.end()) {
187 return std::distance(level_types_.begin(),
index);
193 game_menu_button.
set_values(game_types, get_initial_type_index());
201 mod_list_ = &find_widget<listbox>(&win,
"mod_list",
false);
205 std::map<std::string, string_map> data;
208 item[
"label"] = mod->name;
209 data.emplace(
"mod_name", item);
213 find_widget<toggle_panel>(row_grid,
"panel",
false).set_tooltip(mod->description);
215 toggle_button& mog_toggle = find_widget<toggle_button>(row_grid,
"mod_active_state",
false);
218 if(std::find(activemods.begin(), activemods.end(), mod->id) != activemods.end()) {
236 std::vector<config> era_names;
238 era_names.emplace_back(
"label",
era->name,
"tooltip",
era->description);
241 if(era_names.empty()) {
252 if(era_selection >= 0) {
261 std::vector<config> rfm_options;
265 rfm_options.emplace_back(
"label",
271 rfm_options[0][
"tooltip"] =
_(
"Independent: Random factions assigned independently");
272 rfm_options[1][
"tooltip"] =
_(
"No Mirror: No two players will get the same faction");
273 rfm_options[2][
"tooltip"] =
_(
"No Ally Mirror: No two allied players will get the same faction");
275 const int initial_index = std::distance(rfm_types_.begin(), std::find(rfm_types_.begin(), rfm_types_.end(),
276 mp_game_settings::RANDOM_FACTION_MODE::string_to_enum(
prefs::random_faction_mode(), mp_game_settings::RANDOM_FACTION_MODE::DEFAULT))
279 menu_button& rfm_menu_button = find_widget<menu_button>(&win,
"random_faction_mode",
false);
281 rfm_menu_button.
set_values(rfm_options, initial_index);
291 bind_status_label<slider>(&win,
turns_->
id());
292 bind_status_label<slider>(&win,
gold_->
id());
293 bind_status_label<slider>(&win,
support_->
id());
306 find_widget<text_box>(&win,
"game_name",
false).set_active(
false);
307 find_widget<text_box>(&win,
"game_password",
false).set_active(
false);
317 listbox& tab_bar = find_widget<listbox>(&win,
"tab_bar",
false);
325 find_widget<stacked_widget>(&win,
"pager",
false).set_find_in_all_layers(
true);
332 listbox& list = find_widget<listbox>(&win,
"games_list",
false);
337 win.add_to_keyboard_chain(&list);
354 #define UPDATE_ATTRIBUTE(field, convert) \ 355 do { if(cfg.has_attribute(#field)) { field##_->set_widget_value(win, cfg[#field].convert()); } } while(false) \ 376 #undef UPDATE_ATTRIBUTE 402 "id", current_level.
id(),
403 "name", current_level.
name(),
404 "icon", current_level.
icon(),
412 const std::string
id = cfg[
"id"].str();
430 DBG_MP <<
"sync_with_depcheck: start\n";
433 DBG_MP <<
"sync_with_depcheck: correcting era\n";
441 DBG_MP <<
"sync_with_depcheck: correcting scenario\n";
447 if(new_level_index.second != -1) {
452 auto& game_types_list = find_widget<menu_button>(
get_window(),
"game_types",
false);
462 find_widget<listbox>(
get_window(),
"games_list",
false).select_row(new_level_index.second);
473 DBG_MP <<
"sync_with_depcheck: correcting modifications\n";
478 DBG_MP <<
"sync_with_depcheck: end\n";
481 template<
typename w
idget>
502 const int selected_game = find_widget<listbox>(
get_window(),
"games_list",
false).get_selected_row();
520 if(!can_select_era) {
537 const int i = find_widget<listbox>(
get_window(),
"tab_bar",
false).get_selected_row();
538 find_widget<stacked_widget>(
get_window(),
"pager",
false).select_layer(i);
544 ERR_MP <<
"ignoring on_mod_toggle that is already set\n";
575 description.
set_label(!new_description.empty() ? new_description :
_(
"No description available."));
581 const int index = find_widget<menu_button>(
get_window(),
"game_types",
false).get_value();
595 std::map<std::string, string_map> data;
598 if(type == ng::level::TYPE::CAMPAIGN || type == ng::level::TYPE::SP_CAMPAIGN) {
599 item[
"label"] =
game->icon();
600 data.emplace(
"game_icon", item);
603 item[
"label"] =
game->name();
604 data.emplace(
"game_name", item);
611 on_filter_change<slider>(
"num_players",
false);
612 on_filter_change<text_box>(
"game_filter",
false);
615 if(level_index >= 0 && std::size_t(level_index) < list.
get_item_count()) {
620 const bool is_random_map = type == ng::level::TYPE::RANDOM_MAP;
622 find_widget<button>(
get_window(),
"random_map_regenerate",
false).set_active(is_random_map);
623 find_widget<button>(
get_window(),
"random_map_settings",
false).set_active(is_random_map);
648 return std::distance(filtered_indices.begin(), std::find(filtered_indices.begin(), filtered_indices.end(), initial_index));
677 find_widget<styled_widget>(
get_window(),
"game_title",
false).set_label(title);
683 case ng::level::TYPE::USER_MAP:
684 case ng::level::TYPE::USER_SCENARIO:
685 case ng::level::TYPE::RANDOM_MAP: {
688 assert(current_scenario);
692 find_widget<stacked_widget>(
get_window(),
"minimap_stack",
false).select_layer(0);
694 if(current_scenario->
data()[
"map_data"].
empty()) {
699 find_widget<minimap>(
get_window(),
"minimap",
false).set_map_data(current_scenario->
data()[
"map_data"]);
702 map_size.set_label(current_scenario->
map_size());
706 case ng::level::TYPE::CAMPAIGN:
707 case ng::level::TYPE::SP_CAMPAIGN: {
710 assert(current_campaign);
714 const std::string img =
formatter() << current_campaign->
data()[
"image"] <<
"~SCALE_INTO(265,265)";
716 find_widget<stacked_widget>(
get_window(),
"minimap_stack",
false).select_layer(1);
717 find_widget<image>(
get_window(),
"campaign_image",
false).set_image(img);
723 players.
set_label(
VGETTEXT(
"number of players^$min to $max", {{
"min", std::to_string(p_min)}, {
"max", std::to_string(p_max)}}));
725 players.
set_label(std::to_string(p_min));
766 if(use_map_settings) {
782 if(!
load.load_multiplayer_game()) {
786 if(
load.data().cancel_orders) {
796 std::set<std::string> res;
798 if(find_widget<toggle_button>(
mod_list_->
get_row_grid(i),
"mod_active_state",
false).get_value_bool()) {
803 return std::vector<std::string>(res.begin(), res.end());
808 std::set<std::string> val2(val.begin(), val.end());
810 std::set<std::string> res;
812 find_widget<toggle_button>(
mod_list_->
get_row_grid(i),
"mod_active_state",
false).set_value_bool(val2.find(mod->id) != val2.end());
825 std::stringstream
msg;
827 msg <<
_(
"The selected game cannot be created.");
846 find_widget<stacked_widget>(&window,
"pager",
false).select_layer(-1);
878 std::vector<const config*> entry_points;
879 std::vector<std::string> entry_point_titles;
883 if(tagname ==
"scenario") {
886 const bool is_first = scenario[
"id"] == first_scenario;
888 const std::string& title = !scenario[
"new_game_title"].
empty()
889 ? scenario[
"new_game_title"]
892 entry_points.insert(is_first ? entry_points.begin() : entry_points.end(), &scenario);
893 entry_point_titles.insert(is_first ? entry_point_titles.begin() : entry_point_titles.end(), title);
898 if(entry_points.size() > 1) {
946 const std::string name = find_widget<text_box>(&window,
"game_name",
false).get_value();
952 const std::string
password = find_widget<text_box>(&window,
"game_password",
false).get_value();
953 if(!password.empty()) {
TYPE
Used to specify the rendering format of images.
const std::string & get_scenario() const
Returns the selected scenario.
Dialog was closed with the CANCEL button.
std::string map_size() const
level::TYPE current_level_type() const
void set_value_bool(bool value, bool fire_event=false)
#define REGISTER_DIALOG(window_id)
Wrapper for REGISTER_DIALOG2.
void set_text_changed_callback(std::function< void(text_box_base *textbox, const std::string text)> cb)
Set the text_changed callback.
void sync_with_depcheck()
void set_village_support(int value)
field_integer * reservoir_
const int turns_max
maximum number of turns
void set_current_era_index(const std::size_t index, bool force=false)
std::string random_faction_mode()
The class for loading a savefile.
void set_countdown_action_bonus(int value)
void set_countdown_turn_bonus(int value)
void set_shroud(bool value)
std::vector< mp_game_settings::RANDOM_FACTION_MODE > rfm_types_
void set_countdown_init_time(int value)
bool generator_assigned() const
std::vector< extras_metadata_ptr > & get_extras_by_type(const MP_EXTRA extra_type)
int get_era_index() const
Returns the selected era.
int find_extra_by_id(const MP_EXTRA extra_type, const std::string &id) const
void set_scenario(config scenario)
std::vector< game_tip > load(const config &cfg)
Loads the tips from a config.
static l_noret error(LoadState *S, const char *why)
bool get_value_bool() const
static std::shared_ptr< save_index_class > default_saves_dir()
Returns an instance for managing saves in filesystem::get_saves_dir()
bool generator_has_settings() const
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup, const bool restore_background)
Shows a transient message to the user.
std::vector< level_type_info > level_types_
void display_games_of_type(ng::level::TYPE type, const std::string &level)
void set_current_level(const std::size_t index)
bool is_modification_active(int index) const
Tells whether a certain mod is activated.
void on_mod_toggle(const int index, toggle_button *sender)
void show_generator_settings()
void set_random_faction_mode(const std::string &value)
window * get_window() const
Returns a pointer to the dialog's window.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
field_bool * shuffle_sides_
T get_widget_value(window &window)
Gets the value of the field.
Implements some helper classes to ease adding fields to a dialog and hide the synchronization needed...
static std::string _(const char *str)
bool show(const unsigned auto_close_time=0)
Shows the window.
void set_countdown(bool value)
const mp_game_settings & get_parameters()
void prepare_for_era_and_mods()
bool is_campaign() const
Wrapper to simplify the is-type-campaign-or-sp-campaign check.
void prepare_for_scenario()
int countdown_init_time()
bool current_level_has_side_data()
Returns true if the current level has one or more [side] tags.
std::string dsgettext(const char *domainname, const char *msgid)
bool select_row(const unsigned row, const bool select=true)
Selects a row.
Class for a single line text area.
field_integer * init_turn_limit_
std::string select_campaign_difficulty(int set_value=-1)
select_campaign_difficulty
virtual std::string id() const
const config & data() const
std::vector< std::string > get_active_mods()
void set_current_level_type(const level::TYPE type)
static game_config_manager * get()
field_bool * use_map_settings_
All fields are also in the normal field vector, but they need to be manually controlled as well so ad...
int countdown_turn_bonus()
bool toggle_mod(int index, bool force=false)
void set_level_type(int value)
void set_widget_value(window &window, CT value)
Sets the value of the field.
static void expand_map_file(config &scenario)
reads scenario["map_file"]
A simple one-column listbox with OK and Cancel buttons.
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
virtual std::string name() const
menu_button * eras_menu_button_
const std::string & id() const
void prepare_for_campaign(const std::string &difficulty="")
void clear()
Removes all the rows in the listbox, clearing it.
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
std::unique_ptr< plugins_context > plugins_context_
std::vector< level_ptr > get_levels_by_type_unfiltered(level::TYPE type) const
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button click.
int countdown_reservoir_time()
void set_random_start_time(bool value)
static lg::log_domain log_mp_create("mp/create")
Modify, read and display user preferences.
unsigned get_item_count() const
Returns the number of items in the listbox.
std::string campaign
The id of the campaign being played.
ng::create_engine create_engine_
General settings and defaults for scenarios.
virtual void post_show(window &window) override
Actions to be taken after the window has been shown.
void set_active_mods(const std::vector< std::string > &val)
std::vector< std::string > & active_mods()
void apply_level_filter(const std::string &name)
void load_game_callback()
void init_generated_level_data()
static const int LOAD_GAME
std::pair< level::TYPE, int > find_level_by_id(const std::string &id) const
void set_level(const std::string &value)
#define UPDATE_ATTRIBUTE(field, convert)
field_bool * private_replay_
virtual std::string icon() const
void set_allow_observers(bool value)
std::pair< ng::level::TYPE, std::string > level_type_info
field_integer * action_bonus_
void widget_set_enabled(window &window, const bool enable, const bool sync)
Enables a widget.
void on_filter_change(const std::string &id, bool do_select)
int selected_index() const
Returns the selected item index after displaying.
level & current_level() const
std::unique_ptr< mp_options_helper > options_manager_
int convert_to_game_filtered_index(const unsigned int initial_index)
Game configuration data as global variables.
void update_map_settings()
std::string password(const std::string &server, const std::string &login)
field_integer * turn_bonus_
grid & add_row(const string_map &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
Declarations for File-IO.
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
virtual std::string description() const
field_integer * experience_
boost::dynamic_bitset get_rows_shown() const
Returns a list of visible rows.
std::size_t current_era_index() const
void set_turns(int value)
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
void show_transient_error_message(const std::string &message, const std::string &image, const bool message_use_markup)
Shows a transient error message to the user.
int get_retval() const
Returns the cached window exit code.
const std::vector< std::string > & modifications(bool mp)
const extras_metadata & current_era() const
const depcheck::manager & dependency_manager() const
void generator_user_config()
game_classification & classification()
void set_modifications(const std::vector< std::string > &value, bool mp)
const std::string unicode_em_dash
const std::vector< std::string > & get_modifications() const
Returns the enabled modifications.
Standard logging facilities (interface).
Base class for all level type classes.
std::unique_ptr< ng::configure_engine > config_engine_
field_bool * strict_sync_
const std::vector< extras_metadata_ptr > & get_const_extras_by_type(const MP_EXTRA extra_type) const
int countdown_action_bonus()
void set_era(const std::string &value)
void set_shuffle_sides(bool value)
void on_random_faction_mode_select()
void prepare_for_saved_game()
std::vector< std::size_t > get_filtered_level_indices(level::TYPE type) const
Dialog was closed with the OK button.
bool dialog_exit_hook(window &)
Dialog exit hook to bring up the difficulty dialog when starting a campaign.
A config object defines a single node in a WML file, with access to child nodes.
void show_description(const std::string &new_description)
void prepare_for_new_level()
void set_countdown_reservoir_time(int value)
mp_game_settings & mp_settings()
Multiplayer parameters for this game.
void set_xp_modifier(int value)
void set_retval(int retval)
Convenience wrapper to set the window's exit code.
base class of top level items, the only item which needs to store the final canvases to draw on...
void set_row_shown(const unsigned row, const bool shown)
Makes a row visible or invisible.
void regenerate_random_map()
void set_village_gold(int value)
void set_use_map_settings(bool value)
std::string get_tagname() const
std::pair< std::string, unsigned > item
virtual bool allow_era_choice() const
virtual bool can_launch_game() const =0
void set_single_button(bool value)
Sets whether the Cancel button should be hidden or not.