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