The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
game_classification.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2003 - 2025
3 by David White <dave@whitevine.net>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
17
18#include "config.hpp"
19#include "log.hpp"
23#include "game_version.hpp"
25
26#include <list>
27
28static lg::log_domain log_engine("engine");
29#define ERR_NG LOG_STREAM(err, log_engine)
30#define WRN_NG LOG_STREAM(warn, log_engine)
31#define LOG_NG LOG_STREAM(info, log_engine)
32#define DBG_NG LOG_STREAM(debug, log_engine)
33
34using namespace std::chrono_literals;
35
36/** The default difficulty setting for campaigns. */
37const std::string DEFAULT_DIFFICULTY("NORMAL");
38
40 : label(cfg["label"])
41 , version(cfg["version"])
42 , type(campaign_type::get_enum(cfg["campaign_type"].str()).value_or(campaign_type::type::scenario))
43 , campaign_define(cfg["campaign_define"])
44 , campaign_xtra_defines(utils::split(cfg["campaign_extra_defines"]))
45 , scenario_define(cfg["scenario_define"])
46 , era_define(cfg["era_define"])
47 , mod_defines(utils::split(cfg["mod_defines"]))
48 , active_mods(utils::split(cfg["active_mods"]))
49 , era_id(cfg["era_id"])
50 , campaign(cfg["campaign"])
51 , campaign_name(cfg["campaign_name"])
52 , abbrev(cfg["abbrev"])
53 , end_credits(cfg["end_credits"].to_bool(true))
54 , end_text(cfg["end_text"])
55 , end_text_duration(std::clamp(chrono::parse_duration(cfg["end_text_duration"], 0ms), 0ms, 5000ms))
56 , difficulty(cfg["difficulty"].empty() ? DEFAULT_DIFFICULTY : cfg["difficulty"].str())
57 , random_mode(cfg["random_mode"])
58 , oos_debug(cfg["oos_debug"].to_bool(false))
59{
60}
61
63{
64 config cfg;
65 cfg["label"] = label;
67 cfg["campaign_type"] = campaign_type::get_string(type);
68 cfg["campaign_define"] = campaign_define;
69 cfg["campaign_extra_defines"] = utils::join(campaign_xtra_defines);
70 cfg["scenario_define"] = scenario_define;
71 cfg["era_define"] = era_define;
72 cfg["mod_defines"] = utils::join(mod_defines);
73 cfg["active_mods"] = utils::join(active_mods);
74 cfg["era_id"] = era_id;
75 cfg["campaign"] = campaign;
76 cfg["campaign_name"] = campaign_name;
77 cfg["abbrev"] = abbrev;
78 cfg["end_credits"] = end_credits;
79 cfg["end_text"] = end_text;
80 cfg["end_text_duration"] = end_text_duration;
81 cfg["difficulty"] = difficulty;
82 cfg["random_mode"] = random_mode;
83 cfg["oos_debug"] = oos_debug;
84 cfg["core"] = prefs::get().core();
85
86 return cfg;
87}
88
90{
91 if(is_multiplayer()) {
92 return campaign.empty() ? campaign_type::multiplayer : campaign_type::scenario;
93 }
94
95 if(is_tutorial()) {
96 return campaign_type::scenario;
97 }
98
100}
101
102namespace
103{
104// helper objects for saved_game::expand_mp_events()
105struct modevents_entry
106{
107 modevents_entry(const std::string& _type, const std::string& _id)
108 : type(_type)
109 , id(_id)
110 {
111 }
112
113 std::string type;
114 std::string id;
115};
116}
117
118std::set<std::string> game_classification::active_addons(const std::string& scenario_id) const
119{
120 //FIXME: this doesn't include mods from the current scenario.
121 std::list<modevents_entry> mods;
122 std::set<std::string> loaded_resources;
123 std::set<std::string> res;
124
125 for(const auto& mod : active_mods) {
126 mods.emplace_back("modification", mod);
127 }
128
129 // We don't want the error message below if there is no era (= if this is a sp game).
130 if(!era_id.empty()) {
131 mods.emplace_back(get_tagname(), scenario_id);
132 }
133
134 if(!era_id.empty()) {
135 mods.emplace_back("era", era_id);
136 }
137
138 if(!campaign.empty()) {
139 mods.emplace_back("campaign", campaign);
140 }
141 while(!mods.empty()) {
142
143 const modevents_entry& current = mods.front();
144 if(current.type == "resource") {
145 if(!loaded_resources.insert(current.id).second) {
146 mods.pop_front();
147 continue;
148 }
149 }
150 if(auto cfg = game_config_manager::get()->game_config().find_child(current.type, "id", current.id)) {
151 if(!cfg["addon_id"].empty()) {
152 res.insert(cfg["addon_id"]);
153 }
154 for (const config& load_res : cfg->child_range("load_resource")) {
155 mods.emplace_back("resource", load_res["id"].str());
156 }
157 } else {
158 ERR_NG << "Unable to find config for content " << current.id << " of type " << current.type;
159 }
160 mods.pop_front( );
161 }
162
163 DBG_NG << "Active content for game set to:";
164 for(const std::string& mod : res) {
165 DBG_NG << mod;
166 }
167
168 return res;
169}
#define ERR_NG
#define DBG_NG
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
child_itors child_range(std::string_view key)
Definition config.cpp:268
bool empty() const
Definition config.cpp:823
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::set< std::string > active_addons(const std::string &scenario_id) const
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::chrono::milliseconds end_text_duration
for how long the end-of-campaign text is shown
game_classification()=default
std::vector< std::string > active_mods
campaign_type::type type
bool end_credits
whether to show the standard credits at the end
std::string label
Name of the game (e.g.
std::string campaign_define
If there is a define the campaign uses to customize data.
std::string get_tagname() const
std::string campaign
The id of the campaign being played.
std::string abbrev
the campaign abbreviation
std::string end_text
end-of-campaign text
std::string campaign_name
The name of the campaign being played.
static game_config_manager * get()
const game_config_view & game_config() const
optional_const_config find_child(std::string_view key, const std::string &name, const std::string &value) const
static prefs & get()
std::string str() const
Serializes the version number into string form.
Definitions for the interface to Wesnoth Markup Language (WML).
const config * cfg
static lg::log_domain log_engine("engine")
const std::string DEFAULT_DIFFICULTY
The default difficulty setting for campaigns.
Interfaces for manipulating version numbers of engine, add-ons, etc.
std::string label
What to show in the filter's drop-down list.
Definition manager.cpp:201
std::string id
Text to match against addon_info.tags()
Definition manager.cpp:199
Standard logging facilities (interface).
const version_info wesnoth_version(VERSION)
STL namespace.
std::string join(const Range &v, const std::string &s=",")
Generates a new string joining container items in a list.
The base template for associating string values with enum values.
Definition enum_base.hpp:33
static std::string get_string(enum_type key)
Converts a enum to its string equivalent.
Definition enum_base.hpp:46