The Battle for Wesnoth  1.17.0-dev
game_config.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2021
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 
16 #include "game_config.hpp"
17 
18 #include "color_range.hpp"
19 #include "config.hpp"
20 #include "gettext.hpp"
21 #include "log.hpp"
22 #include "utils/math.hpp"
23 #include "game_version.hpp"
24 #include "wesconfig.h"
26 
27 static lg::log_domain log_engine("engine");
28 #define LOG_NG LOG_STREAM(info, log_engine)
29 #define ERR_NG LOG_STREAM(err, log_engine)
30 
31 namespace game_config
32 {
33 //
34 // Path info
35 //
36 #ifdef WESNOTH_PATH
37 std::string path = WESNOTH_PATH;
38 #else
39 std::string path = "";
40 #endif
41 
42 #ifdef DEFAULT_PREFS_PATH
43 std::string default_preferences_path = DEFAULT_PREFS_PATH;
44 #else
45 std::string default_preferences_path = "";
46 #endif
47 bool check_migration = false;
48 
49 std::string wesnoth_program_dir;
50 
51 //
52 // Gameplay constants
53 //
54 int base_income = 2;
57 int recall_cost = 20;
60 
61 int poison_amount = 8;
63 
65 
66 //
67 // Terrain-related constants
68 //
69 unsigned int tile_size = 72;
70 
71 std::string default_terrain;
73 
74 std::vector<unsigned int> zoom_levels {36, 72, 144};
75 
76 //
77 // Display scale constants
78 //
79 double hp_bar_scaling = 0.666;
80 double xp_bar_scaling = 0.5;
81 double hex_brightening = 1.25;
82 
83 //
84 // Misc
85 //
87 
88 unsigned lobby_network_timer = 100;
89 unsigned lobby_refresh = 4000;
90 
91 const std::string observer_team_name = "observer";
92 
93 const std::size_t max_loop = 65536;
94 
95 std::vector<server_info> server_list;
96 
97 bool allow_insecure = false;
98 
99 //
100 // Gamestate flags
101 //
102 bool
103  debug_impl = false,
104  debug_lua = false,
105  strict_lua = false,
106  editor = false,
108  mp_debug = false,
109  exit_at_end = false,
110  no_delay = false,
112  no_addons = false;
113 
114 const bool& debug = debug_impl;
115 
116 void set_debug(bool new_debug) {
117  if(debug_impl && !new_debug) {
118  // Turning debug mode off; decrease deprecation severity
119  int severity;
120  if(lg::get_log_domain_severity("deprecation", severity)) {
121  lg::set_log_domain_severity("deprecation", severity - 2);
122  }
123  } else if(!debug_impl && new_debug) {
124  // Turning debug mode on; increase deprecation severity
125  int severity;
126  if(lg::get_log_domain_severity("deprecation", severity)) {
127  lg::set_log_domain_severity("deprecation", severity + 2);
128  }
129  }
130  debug_impl = new_debug;
131 }
132 
133 //
134 // Orb display flags
135 //
142 
143 //
144 // Music constants
145 //
147 
148 std::vector<std::string> default_defeat_music;
149 std::vector<std::string> default_victory_music;
150 
151 //
152 // Color info
153 //
154 std::string flag_rgb, unit_rgb;
155 
156 std::vector<color_t> red_green_scale;
157 std::vector<color_t> red_green_scale_text;
158 
159 static std::vector<color_t> blue_white_scale;
160 static std::vector<color_t> blue_white_scale_text;
161 
162 std::map<std::string, color_range> team_rgb_range;
163 // Map [color_range]id to [color_range]name, or "" if no name
164 std::map<std::string, t_string> team_rgb_name;
165 
166 std::map<std::string, std::vector<color_t>> team_rgb_colors;
167 
168 std::vector<std::string> default_colors;
169 
170 namespace colors
171 {
172 std::string ally_orb_color;
174 std::string enemy_orb_color;
175 std::string moved_orb_color;
176 std::string partial_orb_color;
177 std::string unmoved_orb_color;
178 std::string default_color_list;
179 } // namespace colors
180 
181 //
182 // Image constants
183 //
184 std::vector<std::string> foot_speed_prefix;
185 
187 std::string foot_teleport_exit;
188 
189 namespace images {
190 
191 std::string
194  game_logo,
199  // orbs and hp/xp bar
200  orb,
202  energy,
203  // top bar icons
204  battery_icon,
205  time_icon,
206  // flags
207  flag,
208  flag_icon,
209  // hex overlay
210  terrain_mask,
211  grid_top,
212  grid_bottom,
213  mouseover,
214  selected,
215  editor_brush,
216  unreachable,
217  linger,
218  // GUI elements
219  observer,
220  tod_bright,
221  tod_dark,
222  // TODO: de-hardcode this
223  selected_menu = "buttons/radiobox-pressed.png",
224  deselected_menu = "buttons/radiobox.png",
225  checked_menu = "buttons/checkbox-pressed.png",
226  unchecked_menu = "buttons/checkbox.png",
227  wml_menu = "buttons/WML-custom.png",
228  level,
229  ellipsis,
230  missing,
231  // notifications icon
232  app_icon = "images/icons/icon-game.png";
233 
234 } //images
235 
236 //
237 // Sound constants
238 //
239 namespace sounds {
240 
241 std::string
242  turn_bell = "bell.wav",
243  timer_bell = "timer.wav",
244  public_message = "chat-[1~3].ogg",
245  private_message = "chat-highlight.ogg",
246  friend_message = "chat-friend.ogg",
247  server_message = "receive.wav",
248  player_joins = "arrive.wav",
249  player_leaves = "leave.wav",
250  game_user_arrive = "join.wav",
251  game_user_leave = "leave.wav",
252  ready_for_start = "bell.wav",
253  game_has_begun = "gamestart.ogg",
254  game_created = "join.wav";
255 
256 const std::string
257  button_press = "button.wav",
258  checkbox_release = "checkbox.wav",
259  slider_adjust = "slider.wav",
260  menu_expand = "expand.wav",
261  menu_contract = "contract.wav",
262  menu_select = "select.wav";
263 
264 namespace status {
265 
266 std::string
267  poisoned = "poison.ogg",
268  slowed = "slowed.wav",
269  petrified = "petrified.ogg";
270 
271 } // status
272 
273 } // sounds
274 
275 static void add_color_info(const game_config_view& v, bool build_defaults);
277 {
278  add_color_info(v, false);
279 }
280 
281 void load_config(const config &v)
282 {
283  base_income = v["base_income"].to_int(2);
284  village_income = v["village_income"].to_int(1);
285  village_support = v["village_support"].to_int(1);
286  poison_amount = v["poison_amount"].to_int(8);
287  rest_heal_amount = v["rest_heal_amount"].to_int(2);
288  recall_cost = v["recall_cost"].to_int(20);
289  kill_experience = v["kill_experience"].to_int(8);
290  combat_experience= v["combat_experience"].to_int(1);
291  lobby_refresh = v["lobby_refresh"].to_int(2000);
292  default_terrain = v["default_terrain"].str();
293  tile_size = v["tile_size"].to_int(72);
294 
295  std::vector<std::string> zoom_levels_str = utils::split(v["zoom_levels"]);
296  if(!zoom_levels_str.empty()) {
297  zoom_levels.clear();
298  std::transform(zoom_levels_str.begin(), zoom_levels_str.end(), std::back_inserter(zoom_levels), [](const std::string zoom) {
299  return static_cast<int>(std::stold(zoom) * tile_size);
300  });
301  }
302 
303  title_music = v["title_music"].str();
304  lobby_music = v["lobby_music"].str();
305 
306  default_victory_music = utils::split(v["default_victory_music"].str());
307  default_defeat_music = utils::split(v["default_defeat_music"].str());
308 
309  if(const config& i = v.child("colors")){
310  using namespace game_config::colors;
311 
312  moved_orb_color = i["moved_orb_color"].str();
313  unmoved_orb_color = i["unmoved_orb_color"].str();
314  partial_orb_color = i["partial_orb_color"].str();
315  enemy_orb_color = i["enemy_orb_color"].str();
316  ally_orb_color = i["ally_orb_color"].str();
317  disengaged_orb_color = i["disengaged_orb_color"].str();
318  } // colors
319 
320  show_ally_orb = v["show_ally_orb"].to_bool(true);
321  show_enemy_orb = v["show_enemy_orb"].to_bool(false);
322  show_moved_orb = v["show_moved_orb"].to_bool(true);
323  show_partial_orb = v["show_partly_orb"].to_bool(true);
324  show_unmoved_orb = v["show_unmoved_orb"].to_bool(true);
325  show_disengaged_orb = v["show_disengaged_orb"].to_bool(true);
326 
327  if(const config& i = v.child("images")){
328  using namespace game_config::images;
329 
330  game_title = i["game_title"].str();
331  game_title_background = i["game_title_background"].str();
332  game_logo = i["game_logo"].str();
333  game_logo_background = i["game_logo_background"].str();
334 
335  victory_laurel = i["victory_laurel"].str();
336  victory_laurel_hardest = i["victory_laurel_hardest"].str();
337  victory_laurel_easy = i["victory_laurel_easy"].str();
338 
339  orb = i["orb"].str();
340  orb_two_color = i["orb_two_color"].str();
341  energy = i["energy"].str();
342 
343  battery_icon = i["battery_icon"].str();
344  time_icon = i["time_icon"].str();
345 
346  flag = i["flag"].str();
347  flag_icon = i["flag_icon"].str();
348 
349  terrain_mask = i["terrain_mask"].str();
350  grid_top = i["grid_top"].str();
351  grid_bottom = i["grid_bottom"].str();
352  mouseover = i["mouseover"].str();
353  selected = i["selected"].str();
354  editor_brush = i["editor_brush"].str();
355  unreachable = i["unreachable"].str();
356  linger = i["linger"].str();
357 
358  observer = i["observer"].str();
359  tod_bright = i["tod_bright"].str();
360  tod_dark = i["tod_dark"].str();
361  level = i["level"].str();
362  ellipsis = i["ellipsis"].str();
363  missing = i["missing"].str();
364  } // images
365 
366  hp_bar_scaling = v["hp_bar_scaling"].to_double(0.666);
367  xp_bar_scaling = v["xp_bar_scaling"].to_double(0.5);
368  hex_brightening = v["hex_brightening"].to_double(1.25);
369 
370  foot_speed_prefix = utils::split(v["footprint_prefix"]);
371  foot_teleport_enter = v["footprint_teleport_enter"].str();
372  foot_teleport_exit = v["footprint_teleport_exit"].str();
373 
374  shroud_prefix = v["shroud_prefix"].str();
375  fog_prefix = v["fog_prefix"].str();
376 
378 
379  if(const config::attribute_value* a = v.get("flag_rgb")) {
380  flag_rgb = a->str();
381  }
382 
383  if(const config::attribute_value* a = v.get("unit_rgb")) {
384  unit_rgb = a->str();
385  }
386 
387  const auto parse_config_color_list = [&](
388  const std::string& key,
389  const color_t fallback)->std::vector<color_t>
390  {
391  std::vector<color_t> color_vec;
392 
393  for(const auto& s : utils::split(v[key].str())) {
394  try {
395  color_vec.push_back(color_t::from_hex_string(s));
396  } catch(const std::invalid_argument& e) {
397  ERR_NG << "Error parsing color list '" << key << "'.\n" << e.what() << std::endl;
398  color_vec.push_back(fallback);
399  }
400  }
401 
402  return color_vec;
403  };
404 
405  red_green_scale = parse_config_color_list("red_green_scale", {255, 255, 255});
406  red_green_scale_text = parse_config_color_list("red_green_scale_text", {255, 255, 255});
407  blue_white_scale = parse_config_color_list("blue_white_scale", {0 , 0 , 255});
408  blue_white_scale_text = parse_config_color_list("blue_white_scale_text", {0 , 0 , 255});
409 
410  server_list.clear();
411 
412  for(const config& server : v.child_range("server")) {
413  server_info sinf;
414  sinf.name = server["name"].str();
415  sinf.address = server["address"].str();
416  server_list.push_back(sinf);
417  }
418 
419  if(const config& s = v.child("sounds")) {
420  using namespace game_config::sounds;
421 
422  const auto load_attribute = [](const config& c, const std::string& key, std::string& member) {
423  if(c.has_attribute(key)) {
424  member = c[key].str();
425  }
426  };
427 
428  load_attribute(s, "turn_bell", turn_bell);
429  load_attribute(s, "timer_bell", timer_bell);
430  load_attribute(s, "public_message", public_message);
431  load_attribute(s, "private_message", private_message);
432  load_attribute(s, "friend_message", friend_message);
433  load_attribute(s, "server_message", server_message);
434  load_attribute(s, "player_joins", player_joins);
435  load_attribute(s, "player_leaves", player_leaves);
436  load_attribute(s, "game_created", game_created);
437  load_attribute(s, "game_user_arrive", game_user_arrive);
438  load_attribute(s, "game_user_leave", game_user_leave);
439  load_attribute(s, "ready_for_start", ready_for_start);
440  load_attribute(s, "game_has_begun", game_has_begun);
441 
442  if(const config & ss = s.child("status")) {
443  using namespace game_config::sounds::status;
444 
445  load_attribute(ss, "poisoned", poisoned);
446  load_attribute(ss, "slowed", slowed);
447  load_attribute(ss, "petrified", petrified);
448  }
449  }
450 }
451 
452 void add_color_info(const game_config_view& v, bool build_defaults)
453 {
454  if(build_defaults) {
455  default_colors.clear();
456  }
457 
458  for(const config& teamC : v.child_range("color_range")) {
459  const config::attribute_value* a1 = teamC.get("id"), *a2 = teamC.get("rgb");
460  if(!a1 || !a2) {
461  continue;
462  }
463 
464  std::string id = *a1;
465  std::vector<color_t> temp;
466 
467  for(const auto& s : utils::split(*a2)) {
468  try {
469  temp.push_back(color_t::from_hex_string(s));
470  } catch(const std::invalid_argument&) {
471  std::stringstream ss;
472  ss << "can't parse color string:\n" << teamC.debug() << "\n";
473  throw config::error(ss.str());
474  }
475  }
476 
477  team_rgb_range.emplace(id, color_range(temp));
478  team_rgb_name.emplace(id, teamC["name"].t_str());
479 
480  LOG_NG << "registered color range '" << id << "': " << team_rgb_range[id].debug() << '\n';
481 
482  // Ggenerate palette of same name;
483  std::vector<color_t> tp = palette(team_rgb_range[id]);
484  if(!tp.empty()) {
485  team_rgb_colors.emplace(id, tp);
486  }
487 
488  if(build_defaults && teamC["default"].to_bool()) {
489  default_colors.push_back(*a1);
490  }
491  }
492 
493  for(const config &cp : v.child_range("color_palette")) {
494  for(const config::attribute& rgb : cp.attribute_range()) {
495  std::vector<color_t> temp;
496  for(const auto& s : utils::split(rgb.second)) {
497  try {
498  temp.push_back(color_t::from_hex_string(s));
499  } catch(const std::invalid_argument&) {
500  ERR_NG << "Invalid color in palette: " << s << std::endl;
501  }
502  }
503 
504  team_rgb_colors.emplace(rgb.first, temp);
505  LOG_NG << "registered color palette: " << rgb.first << '\n';
506  }
507  }
508 }
509 
511 {
512  default_colors.clear();
513  team_rgb_colors.clear();
514  team_rgb_name.clear();
515  team_rgb_range.clear();
516 }
517 
518 const color_range& color_info(const std::string& name)
519 {
520  auto i = team_rgb_range.find(name);
521  if(i != team_rgb_range.end()) {
522  return i->second;
523  }
524 
525  std::vector<color_t> temp;
526  for(const auto& s : utils::split(name)) {
527  try {
528  temp.push_back(color_t::from_hex_string(s));
529  } catch(const std::invalid_argument&) {
530  throw config::error(_("Invalid color in range: ") + s);
531  }
532  }
533 
534  team_rgb_range.emplace(name, color_range(temp));
535  return color_info(name);
536 }
537 
538 const std::vector<color_t>& tc_info(const std::string& name)
539 {
540  auto i = team_rgb_colors.find(name);
541  if(i != team_rgb_colors.end()) {
542  return i->second;
543  }
544 
545  std::vector<color_t> temp;
546  for(const auto& s : utils::split(name)) {
547  try {
548  temp.push_back(color_t::from_hex_string(s));
549  } catch(const std::invalid_argument&) {
550  static std::vector<color_t> stv;
551  ERR_NG << "Invalid color in palette: " << s << std::endl;
552  return stv;
553  }
554  }
555 
556  team_rgb_colors.emplace(name, temp);
557  return tc_info(name);
558 }
559 
560 color_t red_to_green(int val, bool for_text)
561 {
562  const std::vector<color_t>& color_scale = for_text ? red_green_scale_text : red_green_scale;
563 
564  val = std::clamp(val, 0, 100);
565  const int lvl = (color_scale.size() - 1) * val / 100;
566 
567  return color_scale[lvl];
568 }
569 
570 color_t blue_to_white(int val, bool for_text)
571 {
572  const std::vector<color_t>& color_scale = for_text ? blue_white_scale_text : blue_white_scale;
573 
574  val = std::clamp(val, 0, 100);
575  const int lvl = (color_scale.size() - 1) * val / 100;
576 
577  return color_scale[lvl];
578 }
579 
581 {
582  std::string ret = _("The Battle for Wesnoth") + " - " + revision;
583  return ret;
584 }
585 
586 } // game_config
std::vector< std::string > default_victory_music
std::string battery_icon
std::string game_user_leave
std::string victory_laurel
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:402
std::string tod_dark
bool show_unmoved_orb
double hp_bar_scaling
Definition: game_config.cpp:79
double xp_bar_scaling
Definition: game_config.cpp:80
std::map< std::string, color_range > team_rgb_range
Colors defined by WML [color_range] tags.
int village_support
Definition: game_config.cpp:56
Interfaces for manipulating version numbers of engine, add-ons, etc.
bool check_migration
Definition: game_config.cpp:47
#define ERR_NG
Definition: game_config.cpp:29
Variant for storing WML attributes.
std::string mouseover
std::vector< unsigned int > zoom_levels
Definition: game_config.cpp:74
const std::string menu_expand
std::vector< color_t > palette(const color_range &cr)
Creates a reference color palette from a color range.
Definition: color_range.cpp:84
static l_noret error(LoadState *S, const char *why)
Definition: lundump.cpp:40
static game_config_view wrap(const config &cfg)
color_t blue_to_white(int val, bool for_text)
bool has_attribute(config_key_type key) const
Definition: config.cpp:211
#define a
config_array_view child_range(config_key_type key) const
std::string private_message
std::string game_title
child_itors child_range(config_key_type key)
Definition: config.cpp:344
std::string selected_menu
static std::vector< color_t > blue_white_scale
std::string lobby_music
attribute_map::value_type attribute
Definition: config.hpp:222
std::string unreachable
const std::string slider_adjust
const attribute_value * get(config_key_type key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
Definition: config.cpp:780
std::string unit_rgb
std::string friend_message
std::string get_default_title_string()
const std::string menu_select
std::string unchecked_menu
std::string victory_laurel_easy
std::string enemy_orb_color
static std::string _(const char *str)
Definition: gettext.hpp:93
const std::size_t max_loop
The maximum number of hexes on a map and items in an array and also used as maximum in wml loops...
Definition: game_config.cpp:93
bool show_enemy_orb
std::string player_joins
Definitions for the interface to Wesnoth Markup Language (WML).
std::string address
may include &#39;:&#39; followed by port number
Definition: game_config.hpp:80
void load_config(const config &v)
int rest_heal_amount
Definition: game_config.cpp:62
bool show_ally_orb
std::vector< std::string > default_defeat_music
std::string terrain_mask
std::string disengaged_orb_color
std::string flag_icon
std::string turn_bell
std::string timer_bell
#define LOG_NG
Definition: game_config.cpp:28
std::string ally_orb_color
std::string deselected_menu
bool get_log_domain_severity(const std::string &name, int &severity)
Definition: log.cpp:141
std::string victory_laurel_hardest
std::vector< color_t > red_green_scale_text
unsigned lobby_network_timer
Definition: game_config.cpp:88
std::string game_created
bool disable_autosave
static color_t from_hex_string(const std::string &c)
Creates a new color_t object from a string variable in hex format.
Definition: color.cpp:62
std::string default_color_list
std::string ready_for_start
const int gold_carryover_percentage
Default percentage gold carried over to the next scenario.
Definition: game_config.cpp:64
std::string game_user_arrive
bool ignore_replay_errors
std::string selected
std::string foot_teleport_enter
std::string game_title_background
General math utility functions.
int kill_experience
Definition: game_config.cpp:58
std::string grid_bottom
std::string path
Definition: game_config.cpp:39
std::string game_logo_background
std::string shroud_prefix
Definition: game_config.cpp:72
Manage the empty-palette in the editor.
Definition: action.cpp:30
std::string default_terrain
Definition: game_config.cpp:71
std::string moved_orb_color
static void add_color_info(const game_config_view &v, bool build_defaults)
severity
Definition: log.hpp:64
bool allow_insecure
Definition: game_config.cpp:97
std::string flag_rgb
std::string server_message
Some defines: VERSION, PACKAGE, MIN_SAVEGAME_VERSION.
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:215
std::size_t i
Definition: function.cpp:967
std::map< std::string, std::vector< color_t > > team_rgb_colors
std::string editor_brush
std::string unmoved_orb_color
const std::string revision
Game configuration data as global variables.
Definition: build_info.cpp:59
std::string public_message
int village_income
Definition: game_config.cpp:55
static map_location::DIRECTION s
void reset_color_info()
const std::string menu_contract
A color range definition is made of four reference RGB colors, used for calculating conversions from ...
Definition: color_range.hpp:49
std::vector< color_t > red_green_scale
std::string title_music
bool show_moved_orb
int combat_experience
Definition: game_config.cpp:59
const bool & debug
std::vector< std::string > foot_speed_prefix
std::string observer
bool set_log_domain_severity(const std::string &name, int severity)
Definition: log.cpp:117
std::string player_leaves
const std::string button_press
std::string foot_teleport_exit
color_t red_to_green(int val, bool for_text)
Return a color corresponding to the value val red for val=0 to green for val=100, passing by yellow...
std::vector< std::string > split(const config_attribute_value &val)
unsigned int tile_size
Definition: game_config.cpp:69
unsigned lobby_refresh
Definition: game_config.cpp:89
const color_range & color_info(const std::string &name)
Standard logging facilities (interface).
double hex_brightening
Definition: game_config.cpp:81
std::string tod_bright
std::string game_logo
std::string ellipsis
const std::vector< color_t > & tc_info(const std::string &name)
static std::vector< color_t > blue_white_scale_text
std::string time_icon
#define e
std::string checked_menu
bool show_partial_orb
std::string partial_orb_color
std::vector< std::string > default_colors
std::string orb_two_color
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
mock_char c
std::string wml_menu
std::map< std::string, t_string > team_rgb_name
std::string game_has_begun
bool show_disengaged_orb
std::string grid_top
std::string fog_prefix
Definition: game_config.cpp:72
std::vector< server_info > server_list
Definition: game_config.cpp:95
std::string app_icon
std::string wesnoth_program_dir
Definition: game_config.cpp:49
void set_debug(bool new_debug)
static lg::log_domain log_engine("engine")
std::string default_preferences_path
Definition: game_config.cpp:45
const std::string observer_team_name
observer team name used for observer team chat
Definition: game_config.cpp:91
const std::string checkbox_release
int cache_compression_level
Definition: game_config.cpp:86