16 #define GETTEXT_DOMAIN "wesnoth-lib"
49 #include <boost/algorithm/string.hpp>
53 #define DBG_MP LOG_STREAM(debug, log_mp_create)
54 #define WRN_MP LOG_STREAM(warn, log_mp_create)
55 #define ERR_MP LOG_STREAM(err, log_mp_create)
70 , create_engine_(state)
73 , selected_game_index_(-1)
74 , selected_rfm_index_(-1)
84 , strict_sync_(register_bool("strict_sync", true))
85 , private_replay_(register_bool("private_replay", true))
96 , local_mode_(local_mode)
99 {level_type::type::scenario,
_(
"Scenarios")},
100 {level_type::type::campaign,
_(
"Multiplayer Campaigns")},
101 {level_type::type::sp_campaign,
_(
"Singleplayer Campaigns")},
102 {level_type::type::user_map,
_(
"Custom Maps")},
103 {level_type::type::user_scenario,
_(
"Custom Scenarios")},
104 {level_type::type::random_map,
_(
"Random Maps")},
107 level_types_.erase(std::remove_if(level_types_.begin(), level_types_.end(),
109 return create_engine_.get_levels_by_type_unfiltered(type_info.first).empty();
110 }), level_types_.end());
112 set_show_even_without_video(
true);
114 create_engine_.init_active_mods();
116 create_engine_.get_state().clear();
117 create_engine_.get_state().classification().type = campaign_type::type::multiplayer;
120 set_allow_plugin_skip(
false);
128 find_widget<button>(&win,
"random_map_regenerate",
false),
132 find_widget<button>(&win,
"random_map_settings",
false),
136 find_widget<button>(&win,
"load_game",
false),
151 std::bind(&mp_create_game::on_filter_change<slider>,
this,
"num_players",
true));
153 text_box& filter = find_widget<text_box>(&win,
"game_filter",
false);
156 std::bind(&mp_create_game::on_filter_change<text_box>,
this,
"game_filter",
true));
164 std::vector<config> game_types;
166 game_types.emplace_back(
"label", type_info.second);
169 if(game_types.empty()) {
174 menu_button& game_menu_button = find_widget<menu_button>(&win,
"game_types",
false);
177 auto get_initial_type_index = [
this]()->
int {
179 return info.first == *level_type::get_enum(preferences::level_type());
189 game_menu_button.
set_values(game_types, get_initial_type_index());
197 mod_list_ = &find_widget<listbox>(&win,
"mod_list",
false);
204 item[
"label"] = mod->name;
209 find_widget<toggle_panel>(row_grid,
"panel",
false).set_tooltip(mod->description);
211 toggle_button& mog_toggle = find_widget<toggle_button>(row_grid,
"mod_active_state",
false);
214 if(std::find(activemods.begin(), activemods.end(), mod->id) != activemods.end()) {
232 std::vector<config> era_names;
234 era_names.emplace_back(
"label",
era->name,
"tooltip",
era->description);
237 if(era_names.empty()) {
248 if(era_selection >= 0) {
259 menu_button& rfm_menu_button = find_widget<menu_button>(&win,
"random_faction_mode",
false);
270 bind_status_label<slider>(&win,
turns_->
id());
271 bind_status_label<slider>(&win,
gold_->
id());
272 bind_status_label<slider>(&win,
support_->
id());
284 find_widget<button>(&win,
"reset_timer_defaults",
false),
291 find_widget<text_box>(&win,
"game_name",
false).set_active(
false);
292 find_widget<text_box>(&win,
"game_password",
false).set_active(
false);
302 listbox& tab_bar = find_widget<listbox>(&win,
"tab_bar",
false);
310 find_widget<stacked_widget>(&win,
"pager",
false).set_find_in_all_layers(
true);
317 listbox& list = find_widget<listbox>(&win,
"games_list",
false);
339 #define UPDATE_ATTRIBUTE(field, convert) \
340 do { if(cfg.has_attribute(#field)) { field##_->set_widget_value(cfg[#field].convert()); } } while(false) \
361 #undef UPDATE_ATTRIBUTE
387 "id", current_level.
id(),
388 "name", current_level.
name(),
389 "icon", current_level.
icon(),
397 const std::string
id = cfg[
"id"].str();
415 DBG_MP <<
"sync_with_depcheck: start";
418 DBG_MP <<
"sync_with_depcheck: correcting era";
426 DBG_MP <<
"sync_with_depcheck: correcting scenario";
432 if(new_level_index.second != -1) {
437 auto& game_types_list = find_widget<menu_button>(
get_window(),
"game_types",
false);
447 find_widget<listbox>(
get_window(),
"games_list",
false).select_row(new_level_index.second);
458 DBG_MP <<
"sync_with_depcheck: correcting modifications";
463 DBG_MP <<
"sync_with_depcheck: end";
487 const int selected_game = find_widget<listbox>(
get_window(),
"games_list",
false).get_selected_row();
505 if(!can_select_era) {
522 const int i = find_widget<listbox>(
get_window(),
"tab_bar",
false).get_selected_row();
523 find_widget<stacked_widget>(
get_window(),
"pager",
false).select_layer(
i);
529 ERR_MP <<
"ignoring on_mod_toggle that is already set";
560 description.
set_label(!new_description.empty() ? new_description :
_(
"No description available."));
566 const int index = find_widget<menu_button>(
get_window(),
"game_types",
false).get_value();
583 if(
type == level_type::type::campaign ||
type == level_type::type::sp_campaign) {
596 on_filter_change<slider>(
"num_players",
false);
597 on_filter_change<text_box>(
"game_filter",
false);
600 if(level_index >= 0 && std::size_t(level_index) < list.
get_item_count()) {
605 const bool is_random_map =
type == level_type::type::random_map;
607 find_widget<button>(
get_window(),
"random_map_regenerate",
false).set_active(is_random_map);
608 find_widget<button>(
get_window(),
"random_map_settings",
false).set_active(is_random_map);
633 return std::distance(filtered_indices.begin(), std::find(filtered_indices.begin(), filtered_indices.end(), initial_index));
662 find_widget<styled_widget>(
get_window(),
"game_title",
false).set_label(title);
666 case level_type::type::scenario:
667 case level_type::type::user_map:
668 case level_type::type::user_scenario:
669 case level_type::type::random_map: {
672 assert(current_scenario);
676 find_widget<stacked_widget>(
get_window(),
"minimap_stack",
false).select_layer(0);
678 if(current_scenario->
data()[
"map_data"].
empty()) {
683 find_widget<minimap>(
get_window(),
"minimap",
false).set_map_data(current_scenario->
data()[
"map_data"]);
690 case level_type::type::campaign:
691 case level_type::type::sp_campaign: {
694 assert(current_campaign);
698 const std::string img =
formatter() << current_campaign->
data()[
"image"] <<
"~SCALE_INTO(265,265)";
700 find_widget<stacked_widget>(
get_window(),
"minimap_stack",
false).select_layer(1);
701 find_widget<image>(
get_window(),
"campaign_image",
false).set_image(img);
707 players.
set_label(
VGETTEXT(
"number of players^$min to $max", {{
"min", std::to_string(p_min)}, {
"max", std::to_string(p_max)}}));
709 players.
set_label(std::to_string(p_min));
751 find_widget<button>(
get_window(),
"reset_timer_defaults",
false).set_active(time_limit);
769 if(!
load.load_multiplayer_game()) {
773 if(
load.data().cancel_orders) {
783 std::set<std::string> res;
790 return std::vector<std::string>(res.begin(), res.end());
795 std::set<std::string> val2(val.begin(), val.end());
797 std::set<std::string> res;
799 find_widget<toggle_button>(
mod_list_->
get_row_grid(
i),
"mod_active_state",
false).set_value_bool(val2.find(mod->id) != val2.end());
826 std::stringstream
msg;
828 msg <<
_(
"The selected game cannot be created.");
847 find_widget<stacked_widget>(&
window,
"pager",
false).select_layer(-1);
879 std::vector<const config*> entry_points;
880 std::vector<std::string> entry_point_titles;
884 if(tagname ==
"scenario") {
887 const bool is_first = scenario[
"id"] == first_scenario;
889 const std::string& title = !scenario[
"new_game_title"].
empty()
890 ? scenario[
"new_game_title"]
893 entry_points.insert(is_first ? entry_points.begin() : entry_points.end(), &scenario);
894 entry_point_titles.insert(is_first ? entry_point_titles.begin() : entry_point_titles.end(), title);
899 if(entry_points.size() > 1) {
948 const std::string name = find_widget<text_box>(&
window,
"game_name",
false).get_value();
954 const std::string
password = find_widget<text_box>(&
window,
"game_password",
false).get_value();
A config object defines a single node in a WML file, with access to child nodes.
std::string get_tagname() const
std::string campaign
The id of the campaign being played.
static game_config_manager * get()
Abstract base class for all modal dialogs.
bool show(const unsigned auto_close_time=0)
Shows the window.
int get_retval() const
Returns the cached window exit code.
window * get_window()
Returns a pointer to the dialog's window.
field_bool * shuffle_sides_
void load_game_callback()
field_integer * turn_bonus_
std::unique_ptr< ng::configure_engine > config_engine_
bool dialog_exit_hook(window &)
Dialog exit hook to bring up the difficulty dialog when starting a campaign.
std::pair< level_type::type, std::string > level_type_info
void show_generator_settings()
void display_games_of_type(level_type::type type, const std::string &level)
field_integer * action_bonus_
void set_active_mods(const std::vector< std::string > &val)
void show_description(const std::string &new_description)
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
void sync_with_depcheck()
void update_map_settings()
virtual void post_show(window &window) override
Actions to be taken after the window has been shown.
field_integer * init_turn_limit_
std::unique_ptr< mp_options_helper > options_manager_
field_integer * experience_
menu_button * eras_menu_button_
void reset_timer_settings()
std::vector< level_type_info > level_types_
void on_mod_toggle(const int index, toggle_button *sender)
field_bool * strict_sync_
field_bool * private_replay_
ng::create_engine create_engine_
void on_filter_change(const std::string &id, bool do_select)
void on_random_faction_mode_select()
std::vector< std::string > get_active_mods()
int convert_to_game_filtered_index(const unsigned int initial_index)
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...
void regenerate_random_map()
field_integer * reservoir_
std::unique_ptr< plugins_context > plugins_context_
A simple one-column listbox with OK and Cancel buttons.
void set_single_button(bool value)
Sets whether the Cancel button should be hidden or not.
int selected_index() const
Returns the selected item index after displaying.
const std::string & id() const
void widget_set_enabled(const bool enable, const bool sync)
Enables a widget.
void set_widget_value(CT value)
Sets the value of the field.
T get_widget_value()
Gets the value of the field.
void set_row_shown(const unsigned row, const bool shown)
Makes a row visible or invisible.
grid & add_row(const widget_item &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
bool select_row(const unsigned row, const bool select=true)
Selects a row.
boost::dynamic_bitset get_rows_shown() const
Returns a list of visible rows.
void clear()
Removes all the rows in the listbox, clearing it.
unsigned get_item_count() const
Returns the number of items in the listbox.
void set_value_bool(bool value, bool fire_event=false)
bool get_value_bool() const
void set_text_changed_callback(std::function< void(text_box_base *textbox, const std::string text)> cb)
Set the text_changed callback.
Class for a single line text area.
base class of top level items, the only item which needs to store the final canvases to draw on.
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
void keyboard_capture(widget *widget)
void add_to_keyboard_chain(widget *widget)
Adds the widget to the keyboard chain.
void set_exit_hook(exit_hook mode, std::function< bool(window &)> func)
Sets the window's exit hook.
static const std::string & type()
Static type getter that does not rely on the widget being constructed.
@ on_ok
Run hook only if result is OK.
int find_extra_by_id(const MP_EXTRA extra_type, const std::string &id) const
std::vector< std::size_t > get_filtered_level_indices(level_type::type type) const
void set_current_era_index(const std::size_t index, bool force=false)
std::string select_campaign_difficulty(int set_value=-1)
select_campaign_difficulty
bool generator_has_settings() const
std::vector< std::string > & active_mods()
bool current_level_has_side_data()
Returns true if the current level has one or more [side] tags.
bool generator_assigned() const
level_type::type current_level_type() const
std::vector< extras_metadata_ptr > & get_extras_by_type(const MP_EXTRA extra_type)
const std::vector< extras_metadata_ptr > & get_const_extras_by_type(const MP_EXTRA extra_type) const
void apply_level_filter(const std::string &name)
void prepare_for_new_level()
const depcheck::manager & dependency_manager() const
const extras_metadata & current_era() const
void set_current_level_type(const level_type::type type)
std::pair< level_type::type, int > find_level_by_id(const std::string &id) const
bool is_campaign() const
Wrapper to simplify the is-type-campaign-or-sp-campaign check.
void prepare_for_campaign(const std::string &difficulty="")
std::vector< level_ptr > get_levels_by_type_unfiltered(level_type::type type) const
const mp_game_settings & get_parameters()
void prepare_for_saved_game()
void set_current_level(const std::size_t index)
void generator_user_config()
void prepare_for_era_and_mods()
std::size_t current_era_index() const
bool toggle_mod(int index, bool force=false)
void init_generated_level_data()
void prepare_for_scenario()
level & current_level() const
const std::string & get_scenario() const
Returns the selected scenario.
int get_era_index() const
Returns the selected era.
bool is_modification_active(int index) const
Tells whether a certain mod is activated.
const std::vector< std::string > & get_modifications() const
Returns the enabled modifications.
Base class for all level type classes.
const config & data() const
virtual bool can_launch_game() const =0
virtual std::string id() const
virtual std::string name() const
virtual void set_metadata()=0
virtual bool allow_era_choice() const
virtual std::string icon() const
virtual std::string description() const
std::string map_size() const
game_classification & classification()
mp_game_settings & mp_settings()
Multiplayer parameters for this game.
void set_scenario(config scenario)
static void expand_map_file(config &scenario)
reads scenario["map_file"]
The class for loading a savefile.
static std::shared_ptr< save_index_class > default_saves_dir()
Returns an instance for managing saves in filesystem::get_saves_dir()
Implements some helper classes to ease adding fields to a dialog and hide the synchronization needed.
Declarations for File-IO.
static std::string _(const char *str)
Standard logging facilities (interface).
General settings and defaults for scenarios.
#define REGISTER_DIALOG(window_id)
Wrapper for REGISTER_DIALOG2.
static lg::log_domain log_mp_create("mp/create")
#define UPDATE_ATTRIBUTE(field, convert)
const std::string unicode_em_dash
Game configuration data as global variables.
static const int LOAD_GAME
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
std::vector< game_tip > load(const config &cfg)
Loads the tips from a config.
std::map< std::string, widget_item > widget_data
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.
std::map< std::string, t_string > widget_item
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)
Shows a transient message to the user.
@ OK
Dialog was closed with the OK button.
@ CANCEL
Dialog was closed with the CANCEL button.
std::pair< std::string, unsigned > item
Modify, read and display user preferences.
void set_village_support(int value)
void set_village_gold(int value)
void set_era(const std::string &value)
void set_shuffle_sides(bool value)
void set_allow_observers(bool value)
std::string password(const std::string &server, const std::string &login)
void set_shroud(bool value)
int countdown_init_time()
void set_random_faction_mode(const std::string &value)
void set_modifications(const std::vector< std::string > &value, bool mp)
void set_turns(int value)
void set_xp_modifier(int value)
void set_use_map_settings(bool value)
void set_level_type(int value)
void set_countdown_reservoir_time(int value)
int countdown_turn_bonus()
int countdown_action_bonus()
void set_countdown(bool value)
void set_countdown_init_time(int value)
void set_countdown_action_bonus(int value)
void set_level(const std::string &value)
void set_random_start_time(bool value)
int countdown_reservoir_time()
void erase(const std::string &key)
void set_countdown_turn_bonus(int value)
const std::vector< std::string > & modifications(bool mp)
const int turns_max
maximum number of turns
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.
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
string_enums::enum_base< random_faction_mode_defines > random_faction_mode
Base class for all the errors encountered by the engine.
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
static constexpr std::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.