41 #define ERR_CF LOG_STREAM(err, log_config)
44 #define WRN_MP LOG_STREAM(warn, log_mp_create_engine)
45 #define DBG_MP LOG_STREAM(debug, log_mp_create_engine)
65 return map_.get() !=
nullptr;
70 const std::string& map_data =
data_[
"map_data"];
77 data_[
"description"] =
_(
"Map could not be loaded: ") +
e.message;
79 ERR_CF <<
"map could not be loaded: " <<
e.message;
81 data_[
"description"] =
_(
"Map could not be loaded.");
83 ERR_CF <<
"map could not be loaded: " <<
e.dev_message;
93 if(
map_.get() !=
nullptr) {
106 if(
map_.get() !=
nullptr) {
109 const int map_positions =
map_->num_valid_starting_positions();
112 for(
int pos = 0; pos < map_positions; ++pos) {
114 side[
"side"] = pos + 1;
115 side[
"team_name"] =
"Team " + std::to_string(pos + 1);
116 side[
"canrecruit"] =
true;
117 side[
"controller"] = side_controller::human;
123 if(
scenario[
"allow_player"].to_bool(
true)) {
148 if(!
data_[
"description"].empty()) {
149 return data_[
"description"];
153 return _(
"Custom map.");
159 , generate_whole_scenario_(data_.has_attribute(
"scenario_generation"))
160 , generator_name_(generate_whole_scenario_ ? data_[
"scenario_generation"] : data_[
"map_generation"])
165 data_[
"description"] =
"Error: Random map found with missing generator information. Scenario should have a [generator] child.";
166 data_[
"error_message"] =
"missing [generator] tag";
174 data_[
"description"] =
"Error: Random map found with missing generator information. Scenario should have a [generator] child.";
175 data_[
"error_message"] =
"couldn't find 'scenario_generation' or 'map_generation' attribute";
187 , allow_era_choice_(
level::allow_era_choice())
214 int min =
data_[
"min_players"].to_int(1);
215 int max =
data_[
"max_players"].to_int(1);
234 : current_level_type_()
235 , current_level_index_(0)
236 , current_era_index_(0)
237 , level_name_filter_()
238 , player_count_filter_(1)
241 , user_scenario_names_()
245 , dependency_manager_(nullptr)
246 , generator_(nullptr)
247 , selected_campaign_difficulty_()
258 DBG_MP <<
"restoring game config";
278 DBG_MP <<
"initializing all levels, eras and mods";
299 DBG_MP <<
"initializing generated level data";
307 WRN_MP <<
"Tried to initialized generated level data on a level that wasn't a random map";
314 DBG_MP <<
"** replacing map **";
324 DBG_MP <<
"** replacing scenario **";
330 if(!
data.has_attribute(
"modify_placing")) {
331 data[
"modify_placing"] =
true;
334 const std::string& description = cur_lev->
data()[
"description"];
335 data[
"description"] = description;
343 data[
"error_message"] =
e.what();
370 DBG_MP <<
"preparing mp_game_settings for new level";
386 DBG_MP <<
"preparing data for scenario by reloading game config";
397 DBG_MP <<
"preparing data for campaign by reloading game config";
399 if(!difficulty.empty()) {
420 config {
"next_scenario", current_level_data[
"first_scenario"]}
427 std::vector<std::string> difficulties;
430 difficulties.push_back(
d[
"define"]);
434 if(difficulties.empty()) {
439 if(difficulties.size() == 1) {
440 return difficulties[0];
445 if(set_value != -1) {
446 if(set_value >
static_cast<int>(difficulties.size())) {
447 PLAIN_LOG <<
"incorrect difficulty number: [" <<
448 set_value <<
"]. maximum is [" << difficulties.size() <<
"].\n";
450 }
else if(set_value < 1) {
451 PLAIN_LOG <<
"incorrect difficulty number: [" <<
452 set_value <<
"]. minimum is [1].\n";
455 return difficulties[set_value - 1];
472 DBG_MP <<
"preparing mp_game_settings for saved game";
483 DBG_MP <<
"prepare_for_other";
504 type.second.reset_filter();
524 }
catch (
const std::out_of_range&) {
532 assert(current_random_map);
583 for(
const auto&
game :
type.second.games) {
584 if(
game->id() ==
id) {
585 return {
type.first,
i};
592 return {level_type::type::sp_campaign, -1};
599 if(extra->id ==
id) {
622 std::vector<extras_metadata_ptr> data_vec;
623 std::copy_if(mods.begin(), mods.end(), std::back_inserter(data_vec), [
this](
extras_metadata_ptr mod) {
624 return dependency_manager_->is_modification_active(mod->id);
633 return *
eras_[era_index]->cfg;
638 DBG_MP <<
"getting parameter values";
650 config gen_mp_data = *generic_multiplayer;
653 int dep_index_offset = 0;
656 config user_map_data = gen_mp_data;
663 std::unique_ptr<gamemap> map;
665 map.reset(
new gamemap(user_map_data[
"map_data"]));
669 user_map_data[
"description"] =
_(
"Map could not be loaded: ") +
e.message;
671 ERR_CF <<
"map could not be loaded: " <<
e.message;
689 dep_index_offset = 0;
696 ERR_CF <<
"Caught a config error while parsing user made (editor) scenarios:\n" <<
e.message;
702 if(new_scenario->id().empty())
continue;
704 type_map_[level_type::type::user_scenario].games.push_back(std::move(new_scenario));
708 depinfo[
"id"] =
data[
"id"];
709 depinfo[
"name"] =
data[
"name"];
717 if(!
data[
"allow_new_game"].to_bool(
true))
720 if(!
data[
"campaign_id"].empty())
723 if(
data.has_attribute(
"map_generation") ||
data.has_attribute(
"scenario_generation")) {
733 if(
data[
"id"].empty()) {
734 if(
data[
"name"].empty()) {
735 ERR_CF <<
"Found a [campaign] with neither a name nor an id attribute, ignoring it";
737 ERR_CF <<
"Ignoring a [campaign] with no id attribute, but name '" <<
data[
"name"] <<
"'";
742 const std::string&
type =
data[
"type"];
745 if(
type ==
"mp" || (
type ==
"hybrid" &&
mp)) {
751 new_sp_campaign->mark_if_completed();
753 type_map_[level_type::type::sp_campaign].games.push_back(std::move(new_sp_campaign));
757 auto& sp_campaigns =
type_map_[level_type::type::sp_campaign].games;
760 std::stable_sort(sp_campaigns.begin(), sp_campaigns.end(),
762 return a->data()[
"rank"].to_int(1000) < b->data()[
"rank"].to_int(1000);
770 const std::string extra_name = (extra_type ==
ERA) ?
"era" :
"modification";
773 ? component_availability::type::mp
774 : component_availability::type::hybrid;
776 std::set<std::string> found_ids;
782 if((
type != component_availability::type::mp ||
mp) && (
type != component_availability::type::sp || !
mp) )
784 if(found_ids.insert(extra[
"id"]).second) {
786 new_extras_metadata->id = extra[
"id"].str();
787 new_extras_metadata->name = extra[
"name"].str();
788 new_extras_metadata->description = extra[
"description"].str();
789 new_extras_metadata->cfg = &extra;
791 extras.push_back(std::move(new_extras_metadata));
795 ERR_CF <<
"found " << extra_name <<
" with id=" << extra[
"id"] <<
" twice";
810 std::vector<level_ptr> levels;
812 levels.push_back(lvl);
822 std::vector<level_ptr> levels;
823 for(std::size_t
level : g_list.games_filtered) {
824 levels.push_back(g_list.games[
level]);
835 const std::vector<create_engine::extras_metadata_ptr>&
841 std::vector<create_engine::extras_metadata_ptr>&
A config object defines a single node in a WML file, with access to child nodes.
config & mandatory_child(config_key_type key, int n=0)
Returns the nth child with the given key, or throws an error if there is none.
bool has_child(config_key_type key) const
Determine whether a config has a child or not.
bool has_attribute(config_key_type key) const
child_itors child_range(config_key_type key)
config & add_child(config_key_type key)
std::vector< std::string > campaign_xtra_defines
more customization of data
std::vector< std::string > mod_defines
If there are defines the modifications use to customize data.
std::string scenario_define
If there is a define the scenario uses to customize data.
std::string difficulty
The difficulty level the game is being played on.
std::string era_define
If there is a define the era uses to customize data.
std::vector< std::string > active_mods
bool end_credits
whether to show the standard credits at the end
unsigned int end_text_duration
for how long the end-of-campaign text is shown
std::string campaign_define
If there is a define the campaign uses to customize data.
std::string campaign
The id of the campaign being played.
std::string abbrev
the campaign abbreviation
bool is_multiplayer() const
std::string end_text
end-of-campaign text
std::string campaign_name
The name of the campaign being played.
static game_config_manager * get()
void load_game_config_for_game(const game_classification &classification, const std::string &scenario_id)
void load_game_config_for_create(bool is_mp, bool is_test=false)
optional_const_config optional_child(config_key_type key) const
optional_const_config find_child(config_key_type key, const std::string &name, const std::string &value) const
config_array_view child_range(config_key_type key) const
const config & find_mandatory_child(config_key_type key, const std::string &name, const std::string &value) const
Encapsulates the map of the game.
The campaign mode difficulty menu.
std::string selected_difficulty() const
Returns the selected difficulty define after displaying.
bool show(const unsigned auto_close_time=0)
Shows the window.
std::pair< utils::irdya_date, utils::irdya_date > dates_
campaign(const config &data)
bool can_launch_game() const
std::string level_name_filter_
int find_extra_by_id(const MP_EXTRA extra_type, const std::string &id) const
void reset_level_filters()
create_engine(saved_game &state)
std::shared_ptr< campaign > campaign_ptr
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
std::vector< level_ptr > get_levels_by_type(level_type::type type) const
std::string selected_campaign_difficulty_
bool generator_has_settings() const
std::vector< std::string > & active_mods()
std::vector< std::string > user_map_names_
bool current_level_has_side_data()
Returns true if the current level has one or more [side] tags.
bool generator_assigned() const
std::map< level_type::type, type_list > type_map_
void init_extras(const MP_EXTRA extra_type)
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 extras_metadata & current_era() const
std::size_t current_era_index_
const config & curent_era_cfg() const
std::vector< extras_metadata_ptr > mods_
std::unique_ptr< depcheck::manager > dependency_manager_
std::vector< std::string > user_scenario_names_
std::vector< extras_metadata_ptr > active_mods_data()
std::shared_ptr< level > level_ptr
void apply_level_filters()
const game_config_view & game_config_
Reference to the main game config.
std::unique_ptr< map_generator > generator_
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.
std::vector< extras_metadata_ptr > eras_
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()
std::shared_ptr< extras_metadata > extras_metadata_ptr
void prepare_for_saved_game()
void set_current_level(const std::size_t index)
void generator_user_config()
void prepare_for_era_and_mods()
bool toggle_mod(int index, bool force=false)
void init_generated_level_data()
level_type::type current_level_type_
void prepare_for_scenario()
std::size_t current_level_index_
level & current_level() const
std::shared_ptr< scenario > scenario_ptr
Note to all triers: It's not guaranteed that the specified component will be selected (if the user de...
Base class for all level type classes.
const config & data() const
void set_data(const config &data)
virtual bool allow_era_choice() const
level(const config &data)
bool generate_whole_scenario() const
const config & generator_data() const
random_map(const config &data)
std::string generator_name() const
map_generator * create_map_generator() const
std::unique_ptr< gamemap > map_
scenario(const config &data)
std::string map_size() const
bool can_launch_game() const
user_map(const config &data, const std::string &name, gamemap *map)
std::string description() const
game_classification & classification()
bool is_mid_game_save() const
void expand_scenario()
copies the content of a [scenario] with the correct id attribute from the game config into this objec...
void set_carryover_sides_start(config carryover_sides_start)
std::string get_scenario_id() const
static void post_scenario_generation(const config &old_scenario, config &generated_scenario)
copies attributes & tags from the 'outer' [scenario] to the scenario that is generated by scenario_ge...
mp_game_settings & mp_settings()
Multiplayer parameters for this game.
void set_scenario(config scenario)
void check_require_scenario()
Add addon_id information if needed.
void expand_random_scenario()
takes care of generate_map=, generate_scenario=, map= attributes This should be called before expandi...
static irdya_date read_date(const std::string &date)
static lg::log_domain log_mp_create_engine("mp/create/engine")
static lg::log_domain log_config("config")
Declarations for File-IO.
static std::string _(const char *str)
Standard logging facilities (interface).
map_generator * create_map_generator(const std::string &name, const config &cfg, const config *vars)
void get_files_in_dir(const std::string &dir, std::vector< std::string > *files, std::vector< std::string > *dirs, name_mode mode, filter_mode filter, reorder_mode reorder, file_tree_checksum *checksum)
Get a list of all files and/or directories in a given directory.
std::string get_user_data_dir()
std::string read_map(const std::string &name)
const std::string unicode_multiplication_sign
Game configuration data as global variables.
static bool is_active(const widget *wgt)
Main entry points of multiplayer mode.
bool is_campaign_completed(const std::string &campaign_id)
const std::vector< std::string > & modifications(bool mp)
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.
std::vector< std::string > split(const config_attribute_value &val)
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
Function to use the WML preprocessor on a file.
void read(config &cfg, std::istream &in, abstract_validator *validator)
saved_game_mode::type saved_game
static constexpr std::optional< enum_type > get_enum(const std::string_view value)
Converts a string into its enum equivalent.
Helper class, don't construct this directly.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...