16 #define GETTEXT_DOMAIN "wesnoth-lib"
45 #include <boost/algorithm/string.hpp>
49 #define DBG_MP LOG_STREAM(debug, log_mp_create)
50 #define WRN_MP LOG_STREAM(warn, log_mp_create)
51 #define ERR_MP LOG_STREAM(err, log_mp_create)
63 , create_engine_(state)
66 , selected_game_index_(-1)
67 , selected_rfm_index_(-1)
68 , use_map_settings_(register_bool( "use_map_settings", true,
72 , fog_(register_bool(
"fog",
true,
75 , shroud_(register_bool(
"shroud",
true,
78 , start_time_(register_bool(
"random_start_time",
true,
81 , time_limit_(register_bool(
"time_limit",
true,
85 , shuffle_sides_(register_bool(
"shuffle_sides",
true,
88 , observers_(register_bool(
"observers",
true,
91 , strict_sync_(register_bool(
"strict_sync",
true))
92 , private_replay_(register_bool(
"private_replay",
true))
93 , turns_(register_integer(
"turn_count",
true,
96 , gold_(register_integer(
"village_gold",
true,
99 , support_(register_integer(
"village_support",
true,
102 , experience_(register_integer(
"experience_modifier",
true,
105 , init_turn_limit_(register_integer(
"init_turn_limit",
true,
108 , turn_bonus_(register_integer(
"turn_bonus",
true,
111 , reservoir_(register_integer(
"reservoir",
true,
114 , action_bonus_(register_integer(
"action_bonus",
true,
118 , eras_menu_button_()
119 , local_mode_(local_mode)
122 {level_type::type::scenario,
_(
"Scenarios")},
123 {level_type::type::campaign,
_(
"Multiplayer Campaigns")},
124 {level_type::type::sp_campaign,
_(
"Singleplayer Campaigns")},
125 {level_type::type::user_map,
_(
"Custom Maps")},
126 {level_type::type::user_scenario,
_(
"Custom Scenarios")},
127 {level_type::type::random_map,
_(
"Random Maps")},
130 level_types_.erase(std::remove_if(level_types_.begin(), level_types_.end(),
131 [
this](level_type_info& type_info) {
132 return create_engine_.get_levels_by_type_unfiltered(type_info.first).empty();
133 }), level_types_.end());
135 set_show_even_without_video(
true);
137 create_engine_.init_active_mods();
139 create_engine_.get_state().clear();
140 create_engine_.get_state().classification().type = campaign_type::type::multiplayer;
143 set_allow_plugin_skip(
false);
151 find_widget<button>(&win,
"random_map_regenerate",
false),
155 find_widget<button>(&win,
"random_map_settings",
false),
159 find_widget<button>(&win,
"load_game",
false),
174 std::bind(&mp_create_game::on_filter_change<slider>,
this,
"num_players",
true));
176 text_box& filter = find_widget<text_box>(&win,
"game_filter",
false);
179 std::bind(&mp_create_game::on_filter_change<text_box>,
this,
"game_filter",
true));
187 std::vector<config> game_types;
189 game_types.emplace_back(
"label", type_info.second);
192 if(game_types.empty()) {
197 menu_button& game_menu_button = find_widget<menu_button>(&win,
"game_types",
false);
200 auto get_initial_type_index = [
this]()->
int {
202 return info.first == *level_type::get_enum(prefs::get().level_type());
212 game_menu_button.
set_values(game_types, get_initial_type_index());
220 mod_list_ = &find_widget<listbox>(&win,
"mod_list",
false);
227 item[
"label"] = mod->name;
232 find_widget<toggle_panel>(row_grid,
"panel",
false).set_tooltip(mod->description);
234 toggle_button& mog_toggle = find_widget<toggle_button>(row_grid,
"mod_active_state",
false);
236 if(std::find(activemods.begin(), activemods.end(), mod->id) != activemods.end()) {
254 std::vector<config> era_names;
256 era_names.emplace_back(
"label", era->name,
"tooltip", era->description);
259 if(era_names.empty()) {
270 if(era_selection >= 0) {
281 menu_button& rfm_menu_button = find_widget<menu_button>(&win,
"random_faction_mode",
false);
292 bind_status_label<slider>(&win,
turns_->
id());
293 bind_status_label<slider>(&win,
gold_->
id());
294 bind_status_label<slider>(&win,
support_->
id());
306 find_widget<button>(&win,
"reset_timer_defaults",
false),
313 find_widget<text_box>(&win,
"game_name",
false).set_active(
false);
314 find_widget<text_box>(&win,
"game_password",
false).set_active(
false);
324 listbox& tab_bar = find_widget<listbox>(&win,
"tab_bar",
false);
332 find_widget<stacked_widget>(&win,
"pager",
false).set_find_in_all_layers(
true);
339 listbox& list = find_widget<listbox>(&win,
"games_list",
false);
361 #define UPDATE_ATTRIBUTE(field, convert) \
362 do { if(cfg.has_attribute(#field)) { field##_->set_widget_value(cfg[#field].convert()); } } while(false) \
383 #undef UPDATE_ATTRIBUTE
409 "id", current_level.
id(),
410 "name", current_level.
name(),
411 "icon", current_level.
icon(),
419 const std::string
id = cfg[
"id"].str();
437 DBG_MP <<
"sync_with_depcheck: start";
440 DBG_MP <<
"sync_with_depcheck: correcting era";
448 DBG_MP <<
"sync_with_depcheck: correcting scenario";
454 if(new_level_index.second != -1) {
459 auto& game_types_list = find_widget<menu_button>(
get_window(),
"game_types",
false);
469 find_widget<listbox>(
get_window(),
"games_list",
false).select_row(new_level_index.second);
480 DBG_MP <<
"sync_with_depcheck: correcting modifications";
485 DBG_MP <<
"sync_with_depcheck: end";
509 const int selected_game = find_widget<listbox>(
get_window(),
"games_list",
false).get_selected_row();
527 if(!can_select_era) {
544 const int i = find_widget<listbox>(
get_window(),
"tab_bar",
false).get_selected_row();
545 find_widget<stacked_widget>(
get_window(),
"pager",
false).select_layer(
i);
551 ERR_MP <<
"ignoring on_mod_toggle that is already set";
582 description.
set_label(!new_description.empty() ? new_description :
_(
"No description available."));
588 const int index = find_widget<menu_button>(
get_window(),
"game_types",
false).get_value();
605 if(
type == level_type::type::campaign ||
type == level_type::type::sp_campaign) {
615 auto& icon = find_widget<image>(&rg,
"game_icon",
false);
616 if(icon.get_label().empty()) {
623 on_filter_change<slider>(
"num_players",
false);
624 on_filter_change<text_box>(
"game_filter",
false);
627 if(level_index >= 0 && std::size_t(level_index) < list.
get_item_count()) {
632 const bool is_random_map =
type == level_type::type::random_map;
634 find_widget<button>(
get_window(),
"random_map_regenerate",
false).set_active(is_random_map);
635 find_widget<button>(
get_window(),
"random_map_settings",
false).set_active(is_random_map);
660 return std::distance(filtered_indices.begin(), std::find(filtered_indices.begin(), filtered_indices.end(), initial_index));
689 find_widget<styled_widget>(
get_window(),
"game_title",
false).set_label(title);
693 case level_type::type::scenario:
694 case level_type::type::user_map:
695 case level_type::type::user_scenario:
696 case level_type::type::random_map: {
699 assert(current_scenario);
703 find_widget<stacked_widget>(
get_window(),
"minimap_stack",
false).select_layer(0);
705 if(current_scenario->
data()[
"map_data"].
empty()) {
710 find_widget<minimap>(
get_window(),
"minimap",
false).set_map_data(current_scenario->
data()[
"map_data"]);
717 case level_type::type::campaign:
718 case level_type::type::sp_campaign: {
721 assert(current_campaign);
725 const std::string img =
formatter() << current_campaign->
data()[
"image"] <<
"~SCALE_INTO(265,265)";
727 find_widget<stacked_widget>(
get_window(),
"minimap_stack",
false).select_layer(1);
728 find_widget<image>(
get_window(),
"campaign_image",
false).set_image(img);
734 players.
set_label(
VGETTEXT(
"number of players^$min to $max", {{
"min", std::to_string(p_min)}, {
"max", std::to_string(p_max)}}));
736 players.
set_label(std::to_string(p_min));
778 find_widget<button>(
get_window(),
"reset_timer_defaults",
false).set_active(time_limit);
780 if(use_map_settings) {
796 if(!
load.load_multiplayer_game()) {
800 if(
load.data().cancel_orders) {
810 std::set<std::string> res;
817 return std::vector<std::string>(res.begin(), res.end());
822 std::set<std::string> val2(val.begin(), val.end());
824 std::set<std::string> res;
826 find_widget<toggle_button>(
mod_list_->
get_row_grid(
i),
"mod_active_state",
false).set_value_bool(val2.find(mod->id) != val2.end());
853 std::stringstream
msg;
855 msg <<
_(
"The selected game cannot be created.");
874 find_widget<stacked_widget>(&
window,
"pager",
false).select_layer(-1);
906 std::vector<const config*> entry_points;
907 std::vector<std::string> entry_point_titles;
911 if(tagname ==
"scenario") {
914 const bool is_first = scenario[
"id"] == first_scenario;
916 const std::string& title = !scenario[
"new_game_title"].
empty()
917 ? scenario[
"new_game_title"]
920 entry_points.insert(is_first ? entry_points.begin() : entry_points.end(), &scenario);
921 entry_point_titles.insert(is_first ? entry_point_titles.begin() : entry_point_titles.end(), title);
926 if(entry_points.size() > 1) {
975 const std::string name = find_widget<text_box>(&
window,
"game_name",
false).get_value();
981 const std::string password = find_widget<text_box>(&
window,
"game_password",
false).get_value();
982 if(!password.empty()) {
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 on_mod_toggle(const std::string id, toggle_button *sender)
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_
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_
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.
A widget that allows the user to input text in single line.
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
bool toggle_mod(const std::string &id, bool force=false)
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
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
int countdown_init_time()
void set_countdown_reservoir_time(int value)
void set_turns(int value)
void set_village_gold(int value)
void clear_countdown_init_time()
void set_countdown_action_bonus(int value)
void set_level_type(int value)
void set_xp_modifier(int value)
int countdown_action_bonus()
void set_countdown(bool value)
void set_countdown_turn_bonus(int value)
void set_village_support(int value)
void set_use_map_settings(bool value)
void clear_countdown_turn_bonus()
void set_random_faction_mode(const std::string &value)
void set_random_start_time(bool value)
void set_allow_observers(bool value)
void set_shroud(bool value)
void set_countdown_init_time(int value)
void clear_countdown_reservoir_time()
const std::vector< std::string > & modifications(bool mp=true)
void set_era(const std::string &value)
void set_modifications(const std::vector< std::string > &value, bool mp=true)
void set_shuffle_sides(bool value)
int countdown_reservoir_time()
int countdown_turn_bonus()
void set_level(const std::string &value)
void clear_countdown_action_bonus()
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.
static std::string _(const char *str)
Standard logging facilities (interface).
General settings and defaults for scenarios.
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.
REGISTER_DIALOG(editor_edit_unit)
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
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 utils::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.