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) 69 : create_engine_(state)
72 , selected_game_index_(-1)
73 , selected_rfm_index_(-1)
83 , strict_sync_(register_bool("strict_sync", true))
84 , private_replay_(register_bool("private_replay", true))
95 , local_mode_(local_mode)
98 {level_type::type::scenario,
_(
"Scenarios")},
99 {level_type::type::campaign,
_(
"Multiplayer Campaigns")},
100 {level_type::type::sp_campaign,
_(
"Singleplayer Campaigns")},
101 {level_type::type::user_map,
_(
"Custom Maps")},
102 {level_type::type::user_scenario,
_(
"Custom Scenarios")},
103 {level_type::type::random_map,
_(
"Random Maps")},
106 level_types_.erase(std::remove_if(level_types_.begin(), level_types_.end(),
108 return create_engine_.get_levels_by_type_unfiltered(type_info.first).empty();
109 }), level_types_.end());
111 set_show_even_without_video(
true);
113 create_engine_.init_active_mods();
115 create_engine_.get_state().clear();
116 create_engine_.get_state().classification().type = campaign_type::type::multiplayer;
119 set_allow_plugin_skip(
false);
127 find_widget<button>(&win,
"random_map_regenerate",
false),
131 find_widget<button>(&win,
"random_map_settings",
false),
135 find_widget<button>(&win,
"load_game",
false),
150 std::bind(&mp_create_game::on_filter_change<slider>,
this,
"num_players",
true));
152 text_box& filter = find_widget<text_box>(&win,
"game_filter",
false);
155 std::bind(&mp_create_game::on_filter_change<text_box>,
this,
"game_filter",
true));
158 win.keyboard_capture(&filter);
163 std::vector<config> game_types;
165 game_types.emplace_back(
"label", type_info.second);
168 if(game_types.empty()) {
173 menu_button& game_menu_button = find_widget<menu_button>(&win,
"game_types",
false);
176 auto get_initial_type_index = [
this]()->
int {
181 if(
index != level_types_.end()) {
182 return std::distance(level_types_.begin(),
index);
188 game_menu_button.
set_values(game_types, get_initial_type_index());
196 mod_list_ = &find_widget<listbox>(&win,
"mod_list",
false);
200 std::map<std::string, string_map> data;
203 item[
"label"] = mod->name;
204 data.emplace(
"mod_name", item);
208 find_widget<toggle_panel>(row_grid,
"panel",
false).set_tooltip(mod->description);
210 toggle_button& mog_toggle = find_widget<toggle_button>(row_grid,
"mod_active_state",
false);
213 if(std::find(activemods.begin(), activemods.end(), mod->id) != activemods.end()) {
231 std::vector<config> era_names;
233 era_names.emplace_back(
"label",
era->name,
"tooltip",
era->description);
236 if(era_names.empty()) {
247 if(era_selection >= 0) {
256 static const random_faction_mode::sized_array<t_string>
names {
_(
"Independent"),
_(
"No Mirror"),
_(
"No Ally Mirror")};
257 static const random_faction_mode::sized_array<t_string>
tooltips {
258 _(
"Independent: Random factions assigned independently"),
259 _(
"No Mirror: No two players will get the same faction"),
260 _(
"No Ally Mirror: No two allied players will get the same faction")
262 std::vector<config> rfm_options;
264 rfm_options.emplace_back(
"label",
names[
i]);
270 menu_button& rfm_menu_button = find_widget<menu_button>(&win,
"random_faction_mode",
false);
272 rfm_menu_button.
set_values(rfm_options, initial_index);
282 bind_status_label<slider>(&win,
turns_->
id());
283 bind_status_label<slider>(&win,
gold_->
id());
284 bind_status_label<slider>(&win,
support_->
id());
296 find_widget<button>(&win,
"reset_timer_defaults",
false),
303 find_widget<text_box>(&win,
"game_name",
false).set_active(
false);
304 find_widget<text_box>(&win,
"game_password",
false).set_active(
false);
314 listbox& tab_bar = find_widget<listbox>(&win,
"tab_bar",
false);
322 find_widget<stacked_widget>(&win,
"pager",
false).set_find_in_all_layers(
true);
329 listbox& list = find_widget<listbox>(&win,
"games_list",
false);
334 win.add_to_keyboard_chain(&list);
351 #define UPDATE_ATTRIBUTE(field, convert) \ 352 do { if(cfg.has_attribute(#field)) { field##_->set_widget_value(cfg[#field].convert()); } } while(false) \ 373 #undef UPDATE_ATTRIBUTE 399 "id", current_level.
id(),
400 "name", current_level.
name(),
401 "icon", current_level.
icon(),
409 const std::string
id = cfg[
"id"].str();
427 DBG_MP <<
"sync_with_depcheck: start\n";
430 DBG_MP <<
"sync_with_depcheck: correcting era\n";
438 DBG_MP <<
"sync_with_depcheck: correcting scenario\n";
444 if(new_level_index.second != -1) {
449 auto& game_types_list = find_widget<menu_button>(
get_window(),
"game_types",
false);
459 find_widget<listbox>(
get_window(),
"games_list",
false).select_row(new_level_index.second);
470 DBG_MP <<
"sync_with_depcheck: correcting modifications\n";
475 DBG_MP <<
"sync_with_depcheck: end\n";
478 template<
typename w
idget>
499 const int selected_game = find_widget<listbox>(
get_window(),
"games_list",
false).get_selected_row();
517 if(!can_select_era) {
534 const int i = find_widget<listbox>(
get_window(),
"tab_bar",
false).get_selected_row();
535 find_widget<stacked_widget>(
get_window(),
"pager",
false).select_layer(i);
541 ERR_MP <<
"ignoring on_mod_toggle that is already set\n";
572 description.
set_label(!new_description.empty() ? new_description :
_(
"No description available."));
578 const int index = find_widget<menu_button>(
get_window(),
"game_types",
false).get_value();
592 std::map<std::string, string_map> data;
595 if(type == level_type::type::campaign || type == level_type::type::sp_campaign) {
596 item[
"label"] =
game->icon();
597 data.emplace(
"game_icon", item);
600 item[
"label"] =
game->name();
601 data.emplace(
"game_name", item);
608 on_filter_change<slider>(
"num_players",
false);
609 on_filter_change<text_box>(
"game_filter",
false);
612 if(level_index >= 0 && std::size_t(level_index) < list.
get_item_count()) {
617 const bool is_random_map = type == level_type::type::random_map;
619 find_widget<button>(
get_window(),
"random_map_regenerate",
false).set_active(is_random_map);
620 find_widget<button>(
get_window(),
"random_map_settings",
false).set_active(is_random_map);
645 return std::distance(filtered_indices.begin(), std::find(filtered_indices.begin(), filtered_indices.end(), initial_index));
674 find_widget<styled_widget>(
get_window(),
"game_title",
false).set_label(title);
679 case level_type::type::scenario:
680 case level_type::type::user_map:
681 case level_type::type::user_scenario:
682 case level_type::type::random_map: {
685 assert(current_scenario);
689 find_widget<stacked_widget>(
get_window(),
"minimap_stack",
false).select_layer(0);
691 if(current_scenario->
data()[
"map_data"].
empty()) {
696 find_widget<minimap>(
get_window(),
"minimap",
false).set_map_data(current_scenario->
data()[
"map_data"]);
699 map_size.set_label(current_scenario->
map_size());
703 case level_type::type::campaign:
704 case level_type::type::sp_campaign: {
707 assert(current_campaign);
711 const std::string img =
formatter() << current_campaign->
data()[
"image"] <<
"~SCALE_INTO(265,265)";
713 find_widget<stacked_widget>(
get_window(),
"minimap_stack",
false).select_layer(1);
714 find_widget<image>(
get_window(),
"campaign_image",
false).set_image(img);
720 players.
set_label(
VGETTEXT(
"number of players^$min to $max", {{
"min", std::to_string(p_min)}, {
"max", std::to_string(p_max)}}));
722 players.
set_label(std::to_string(p_min));
761 find_widget<button>(
get_window(),
"reset_timer_defaults",
false).set_active(time_limit);
763 if(use_map_settings) {
779 if(!
load.load_multiplayer_game()) {
783 if(
load.data().cancel_orders) {
793 std::set<std::string> res;
795 if(find_widget<toggle_button>(
mod_list_->
get_row_grid(i),
"mod_active_state",
false).get_value_bool()) {
800 return std::vector<std::string>(res.begin(), res.end());
805 std::set<std::string> val2(val.begin(), val.end());
807 std::set<std::string> res;
809 find_widget<toggle_button>(
mod_list_->
get_row_grid(i),
"mod_active_state",
false).set_value_bool(val2.find(mod->id) != val2.end());
836 std::stringstream
msg;
838 msg <<
_(
"The selected game cannot be created.");
857 find_widget<stacked_widget>(&window,
"pager",
false).select_layer(-1);
889 std::vector<const config*> entry_points;
890 std::vector<std::string> entry_point_titles;
894 if(tagname ==
"scenario") {
897 const bool is_first = scenario[
"id"] == first_scenario;
899 const std::string& title = !scenario[
"new_game_title"].
empty()
900 ? scenario[
"new_game_title"]
903 entry_points.insert(is_first ? entry_points.begin() : entry_points.end(), &scenario);
904 entry_point_titles.insert(is_first ? entry_point_titles.begin() : entry_point_titles.end(), title);
909 if(entry_points.size() > 1) {
958 const std::string name = find_widget<text_box>(&window,
"game_name",
false).get_value();
964 const std::string
password = find_widget<text_box>(&window,
"game_password",
false).get_value();
965 if(!password.empty()) {
const std::string & get_scenario() const
Returns the selected scenario.
Dialog was closed with the CANCEL button.
std::string map_size() 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)
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)
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)
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
int get_era_index() const
Returns the selected era.
string_enums::enum_base< random_faction_mode_defines > random_faction_mode
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.
std::pair< level_type::type, std::string > level_type_info
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()
void set_current_level_type(const level_type::type type)
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.
void set_widget_value(CT value)
Sets the value of the field.
std::vector< level_type_info > level_types_
void set_current_level(const std::size_t index)
std::vector< std::size_t > get_filtered_level_indices(level_type::type type) const
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)
std::vector< level_ptr > get_levels_by_type_unfiltered(level_type::type type) const
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_
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.
static constexpr std::size_t size()
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()
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)
static void expand_map_file(config &scenario)
reads scenario["map_file"]
A simple one-column listbox with OK and Cancel buttons.
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_
int countdown_reservoir_time()
void erase(const std::string &key)
void set_random_start_time(bool value)
virtual void set_metadata()=0
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
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)
field_integer * action_bonus_
level_type::type current_level_type() const
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()
static std::string get_string(typename T::type key)
Uses the int value of the provided enum to get the associated index of the values array in the implem...
std::vector< std::string > names
std::string password(const std::string &server, const std::string &login)
field_integer * turn_bonus_
std::pair< level_type::type, int > find_level_by_id(const std::string &id) const
T get_widget_value()
Gets the value of the field.
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.
void reset_timer_settings()
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
static std::optional< typename T::type > get_enum(const std::string value)
Convert a string into its enum equivalent.
Base class for all the errors encountered by the engine.
void generator_user_config()
void widget_set_enabled(const bool enable, const bool sync)
Enables a widget.
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()
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.
void display_games_of_type(level_type::type type, const std::string &level)
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
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
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.