The Battle for Wesnoth  1.15.1+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/general.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 
48 std::string wesnoth_program_dir;
49 
50 //
51 // Gameplay constants
52 //
53 int base_income = 2;
56 int recall_cost = 20;
59 
60 int poison_amount = 8;
62 
64 
65 //
66 // Terrain-related constants
67 //
68 unsigned int tile_size = 72;
69 
70 std::string default_terrain;
72 
73 std::vector<unsigned int> zoom_levels {36, 72, 144};
74 
75 //
76 // Display scale constants
77 //
78 double hp_bar_scaling = 0.666;
79 double xp_bar_scaling = 0.5;
80 double hex_brightening = 1.25;
81 
82 //
83 // Misc
84 //
86 
87 unsigned lobby_network_timer = 100;
88 unsigned lobby_refresh = 4000;
89 
90 const std::string observer_team_name = "observer";
91 
92 const std::size_t max_loop = 65536;
93 
94 std::vector<server_info> server_list;
95 
96 //
97 // Gamestate flags
98 //
99 bool
100  debug_impl = false,
101  debug_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 flahs
131 //
132 bool
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 std::map<std::string, t_string> team_rgb_name;
160 
161 std::map<std::string, std::vector<color_t>> team_rgb_colors;
162 
163 std::vector<std::string> default_colors;
164 
165 namespace colors {
166 
167 std::string
174 
175 } // 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,
197  energy,
198  // top bar icons
199  battery_icon,
200  time_icon,
201  // flags
202  flag,
203  flag_icon,
204  // hex overlay
205  terrain_mask,
206  grid_top,
207  grid_bottom,
208  mouseover,
209  selected,
210  editor_brush,
211  unreachable,
212  linger,
213  // GUI elements
214  observer,
215  tod_bright,
216  tod_dark,
217  ///@todo de-hardcode this
218  selected_menu = "buttons/radiobox-pressed.png",
219  deselected_menu = "buttons/radiobox.png",
220  checked_menu = "buttons/checkbox-pressed.png",
221  unchecked_menu = "buttons/checkbox.png",
222  wml_menu = "buttons/WML-custom.png",
223  level,
224  ellipsis,
225  missing,
226  // notifications icon
227  app_icon = "images/icons/icon-game.png";
228 
229 } //images
230 
231 //
232 // Sound constants
233 //
234 namespace sounds {
235 
236 std::string
237  turn_bell = "bell.wav",
238  timer_bell = "timer.wav",
239  public_message = "chat-[1~3].ogg",
240  private_message = "chat-highlight.ogg",
241  friend_message = "chat-friend.ogg",
242  server_message = "receive.wav",
243  player_joins = "arrive.wav",
244  player_leaves = "leave.wav",
245  game_user_arrive = "join.wav",
246  game_user_leave = "leave.wav",
247  ready_for_start = "bell.wav",
248  game_has_begun = "gamestart.ogg";
249 
250 const std::string
251  button_press = "button.wav",
252  checkbox_release = "checkbox.wav",
253  slider_adjust = "slider.wav",
254  menu_expand = "expand.wav",
255  menu_contract = "contract.wav",
256  menu_select = "select.wav";
257 
258 namespace status {
259 
260 std::string
261  poisoned = "poison.ogg",
262  slowed = "slowed.wav",
263  petrified = "petrified.ogg";
264 
265 } // status
266 
267 } // sounds
268 
269 static void add_color_info(const config& v, bool build_defaults);
270 void add_color_info(const config& v)
271 {
272  add_color_info(v, false);
273 }
274 
275 void load_config(const config &v)
276 {
277  base_income = v["base_income"].to_int(2);
278  village_income = v["village_income"].to_int(1);
279  village_support = v["village_support"].to_int(1);
280  poison_amount = v["poison_amount"].to_int(8);
281  rest_heal_amount = v["rest_heal_amount"].to_int(2);
282  recall_cost = v["recall_cost"].to_int(20);
283  kill_experience = v["kill_experience"].to_int(8);
284  combat_experience= v["combat_experience"].to_int(1);
285  lobby_refresh = v["lobby_refresh"].to_int(2000);
286  default_terrain = v["default_terrain"].str();
287  tile_size = v["tile_size"].to_int(72);
288 
289  std::vector<std::string> zoom_levels_str = utils::split(v["zoom_levels"]);
290  if(!zoom_levels_str.empty()) {
291  zoom_levels.clear();
292  std::transform(zoom_levels_str.begin(), zoom_levels_str.end(), std::back_inserter(zoom_levels), [](const std::string zoom) {
293  return static_cast<int>(std::stold(zoom) * tile_size);
294  });
295  }
296 
297  title_music = v["title_music"].str();
298  lobby_music = v["lobby_music"].str();
299 
300  default_victory_music = utils::split(v["default_victory_music"].str());
301  default_defeat_music = utils::split(v["default_defeat_music"].str());
302 
303  if(const config& i = v.child("colors")){
304  using namespace game_config::colors;
305 
306  moved_orb_color = i["moved_orb_color"].str();
307  unmoved_orb_color = i["unmoved_orb_color"].str();
308  partial_orb_color = i["partial_orb_color"].str();
309  enemy_orb_color = i["enemy_orb_color"].str();
310  ally_orb_color = i["ally_orb_color"].str();
311  } // colors
312 
313  show_ally_orb = v["show_ally_orb"].to_bool(true);
314  show_enemy_orb = v["show_enemy_orb"].to_bool(false);
315  show_moved_orb = v["show_moved_orb"].to_bool(true);
316  show_partial_orb = v["show_partly_orb"].to_bool(true);
317  show_unmoved_orb = v["show_unmoved_orb"].to_bool(true);
318 
319  if(const config& i = v.child("images")){
320  using namespace game_config::images;
321 
322  game_title = i["game_title"].str();
323  game_title_background = i["game_title_background"].str();
324  game_logo = i["game_logo"].str();
325  game_logo_background = i["game_logo_background"].str();
326 
327  victory_laurel = i["victory_laurel"].str();
328  victory_laurel_hardest = i["victory_laurel_hardest"].str();
329  victory_laurel_easy = i["victory_laurel_easy"].str();
330 
331  orb = i["orb"].str();
332  energy = i["energy"].str();
333 
334  battery_icon = i["battery_icon"].str();
335  time_icon = i["time_icon"].str();
336 
337  flag = i["flag"].str();
338  flag_icon = i["flag_icon"].str();
339 
340  terrain_mask = i["terrain_mask"].str();
341  grid_top = i["grid_top"].str();
342  grid_bottom = i["grid_bottom"].str();
343  mouseover = i["mouseover"].str();
344  selected = i["selected"].str();
345  editor_brush = i["editor_brush"].str();
346  unreachable = i["unreachable"].str();
347  linger = i["linger"].str();
348 
349  observer = i["observer"].str();
350  tod_bright = i["tod_bright"].str();
351  tod_dark = i["tod_dark"].str();
352  level = i["level"].str();
353  ellipsis = i["ellipsis"].str();
354  missing = i["missing"].str();
355  } // images
356 
357  hp_bar_scaling = v["hp_bar_scaling"].to_double(0.666);
358  xp_bar_scaling = v["xp_bar_scaling"].to_double(0.5);
359  hex_brightening = v["hex_brightening"].to_double(1.25);
360 
361  foot_speed_prefix = utils::split(v["footprint_prefix"]);
362  foot_teleport_enter = v["footprint_teleport_enter"].str();
363  foot_teleport_exit = v["footprint_teleport_exit"].str();
364 
365  shroud_prefix = v["shroud_prefix"].str();
366  fog_prefix = v["fog_prefix"].str();
367 
368  add_color_info(v, true);
369 
370  if(const config::attribute_value* a = v.get("flag_rgb")) {
371  flag_rgb = a->str();
372  }
373 
374  if(const config::attribute_value* a = v.get("unit_rgb")) {
375  unit_rgb = a->str();
376  }
377 
378  const auto parse_config_color_list = [&](
379  const std::string& key,
380  const color_t fallback)->std::vector<color_t>
381  {
382  std::vector<color_t> color_vec;
383 
384  for(const auto& s : utils::split(v[key].str())) {
385  try {
386  color_vec.push_back(color_t::from_hex_string(s));
387  } catch(const std::invalid_argument& e) {
388  ERR_NG << "Error parsing color list '" << key << "'.\n" << e.what() << std::endl;
389  color_vec.push_back(fallback);
390  }
391  }
392 
393  return color_vec;
394  };
395 
396  red_green_scale = parse_config_color_list("red_green_scale", {255, 255, 255});
397  red_green_scale_text = parse_config_color_list("red_green_scale_text", {255, 255, 255});
398  blue_white_scale = parse_config_color_list("blue_white_scale", {0 , 0 , 255});
399  blue_white_scale_text = parse_config_color_list("blue_white_scale_text", {0 , 0 , 255});
400 
401  server_list.clear();
402 
403  for(const config& server : v.child_range("server")) {
404  server_info sinf;
405  sinf.name = server["name"].str();
406  sinf.address = server["address"].str();
407  server_list.push_back(sinf);
408  }
409 
410  if(const config& s = v.child("sounds")) {
411  using namespace game_config::sounds;
412 
413  const auto load_attribute = [](const config& c, const std::string& key, std::string& member) {
414  if(c.has_attribute(key)) {
415  member = c[key].str();
416  }
417  };
418 
419  load_attribute(s, "turn_bell", turn_bell);
420  load_attribute(s, "timer_bell", timer_bell);
421  load_attribute(s, "public_message", public_message);
422  load_attribute(s, "private_message", private_message);
423  load_attribute(s, "friend_message", friend_message);
424  load_attribute(s, "server_message", server_message);
425  load_attribute(s, "player_joins", player_joins);
426  load_attribute(s, "player_leaves", player_leaves);
427  load_attribute(s, "game_user_arrive", game_user_arrive);
428  load_attribute(s, "game_user_leave", game_user_leave);
429  load_attribute(s, "ready_for_start", ready_for_start);
430  load_attribute(s, "game_has_begun", game_has_begun);
431 
432  if(const config & ss = s.child("status")) {
433  using namespace game_config::sounds::status;
434 
435  load_attribute(ss, "poisoned", poisoned);
436  load_attribute(ss, "slowed", slowed);
437  load_attribute(ss, "petrified", petrified);
438  }
439  }
440 }
441 
442 void add_color_info(const config& v, bool build_defaults)
443 {
444  if(build_defaults) {
445  default_colors.clear();
446  }
447 
448  for(const config& teamC : v.child_range("color_range")) {
449  const config::attribute_value* a1 = teamC.get("id"), *a2 = teamC.get("rgb");
450  if(!a1 || !a2) {
451  continue;
452  }
453 
454  std::string id = *a1;
455  std::vector<color_t> temp;
456 
457  for(const auto& s : utils::split(*a2)) {
458  try {
459  temp.push_back(color_t::from_hex_string(s));
460  } catch(const std::invalid_argument&) {
461  std::stringstream ss;
462  ss << "can't parse color string:\n" << teamC.debug() << "\n";
463  throw config::error(ss.str());
464  }
465  }
466 
467  team_rgb_range.emplace(id, color_range(temp));
468  team_rgb_name.emplace(id, teamC["name"].t_str());
469 
470  LOG_NG << "registered color range '" << id << "': " << team_rgb_range[id].debug() << '\n';
471 
472  // Ggenerate palette of same name;
473  std::vector<color_t> tp = palette(team_rgb_range[id]);
474  if(!tp.empty()) {
475  team_rgb_colors.emplace(id, tp);
476  }
477 
478  if(build_defaults && teamC["default"].to_bool()) {
479  default_colors.push_back(*a1);
480  }
481  }
482 
483  for(const config &cp : v.child_range("color_palette")) {
484  for(const config::attribute& rgb : cp.attribute_range()) {
485  std::vector<color_t> temp;
486  for(const auto& s : utils::split(rgb.second)) {
487  try {
488  temp.push_back(color_t::from_hex_string(s));
489  } catch(const std::invalid_argument&) {
490  ERR_NG << "Invalid color in palette: " << s << std::endl;
491  }
492  }
493 
494  team_rgb_colors.emplace(rgb.first, temp);
495  LOG_NG << "registered color palette: " << rgb.first << '\n';
496  }
497  }
498 }
499 
501 {
502  default_colors.clear();
503  team_rgb_colors.clear();
504  team_rgb_name.clear();
505  team_rgb_range.clear();
506 }
507 
508 const color_range& color_info(const std::string& name)
509 {
510  auto i = team_rgb_range.find(name);
511  if(i != team_rgb_range.end()) {
512  return i->second;
513  }
514 
515  std::vector<color_t> temp;
516  for(const auto& s : utils::split(name)) {
517  try {
518  temp.push_back(color_t::from_hex_string(s));
519  } catch(const std::invalid_argument&) {
520  throw config::error(_("Invalid color in range: ") + s);
521  }
522  }
523 
524  team_rgb_range.emplace(name, color_range(temp));
525  return color_info(name);
526 }
527 
528 const std::vector<color_t>& tc_info(const std::string& name)
529 {
530  auto i = team_rgb_colors.find(name);
531  if(i != team_rgb_colors.end()) {
532  return i->second;
533  }
534 
535  std::vector<color_t> temp;
536  for(const auto& s : utils::split(name)) {
537  try {
538  temp.push_back(color_t::from_hex_string(s));
539  } catch(const std::invalid_argument&) {
540  static std::vector<color_t> stv;
541  ERR_NG << "Invalid color in palette: " << s << std::endl;
542  return stv;
543  }
544  }
545 
546  team_rgb_colors.emplace(name, temp);
547  return tc_info(name);
548 }
549 
550 color_t red_to_green(int val, bool for_text)
551 {
552  const std::vector<color_t>& color_scale = for_text ? red_green_scale_text : red_green_scale;
553 
554  val = utils::clamp(val, 0, 100);
555  const int lvl = (color_scale.size() - 1) * val / 100;
556 
557  return color_scale[lvl];
558 }
559 
560 color_t blue_to_white(int val, bool for_text)
561 {
562  const std::vector<color_t>& color_scale = for_text ? blue_white_scale_text : blue_white_scale;
563 
564  val = utils::clamp(val, 0, 100);
565  const int lvl = (color_scale.size() - 1) * val / 100;
566 
567  return color_scale[lvl];
568 }
569 
571 {
572  std::string ret = _("The Battle for Wesnoth") + " - " + revision;
573  return ret;
574 }
575 
576 } // game_config
constexpr const T & clamp(const T &value, const T &min, const T &max)
Definition: general.hpp:31
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:420
std::string tod_dark
bool show_unmoved_orb
double hp_bar_scaling
Definition: game_config.cpp:78
double xp_bar_scaling
Definition: game_config.cpp:79
std::map< std::string, color_range > team_rgb_range
int village_support
Definition: game_config.cpp:55
Interfaces for manipulating version numbers of engine, add-ons, etc.
#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:73
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:39
color_t blue_to_white(int val, bool for_text)
bool has_attribute(config_key_type key) const
Definition: config.cpp:213
#define a
std::string private_message
std::string game_title
child_itors child_range(config_key_type key)
Definition: config.cpp:362
std::string selected_menu
static std::vector< color_t > blue_white_scale
std::string lobby_music
attribute_map::value_type attribute
Definition: config.hpp:256
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:742
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
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:92
bool show_enemy_orb
std::string player_joins
Definitions for the interface to Wesnoth Markup Language (WML).
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
std::string address
may include &#39;:&#39; followed by port number
Definition: game_config.hpp:75
void load_config(const config &v)
static void add_color_info(const config &v, bool build_defaults)
int rest_heal_amount
Definition: game_config.cpp:61
bool show_ally_orb
std::vector< std::string > default_defeat_music
std::string terrain_mask
std::string flag_icon
std::string turn_bell
std::string timer_bell
static const char * name(const std::vector< SDL_Joystick *> &joysticks, const std::size_t index)
Definition: joystick.cpp:48
#define LOG_NG
Definition: game_config.cpp:28
std::string ally_orb_color
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:91
std::string deselected_menu
bool get_log_domain_severity(const std::string &name, int &severity)
Definition: log.cpp:142
std::string victory_laurel_hardest
std::vector< color_t > red_green_scale_text
unsigned lobby_network_timer
Definition: game_config.cpp:87
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:63
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:57
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:71
Manage the empty-palette in the editor.
Definition: action.cpp:29
std::string default_terrain
Definition: game_config.cpp:70
std::string moved_orb_color
std::string flag_rgb
std::string server_message
Some defines: VERSION, PACKAGE, MIN_SAVEGAME_VERSION.
std::size_t i
Definition: function.cpp:933
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:49
std::string public_message
int village_income
Definition: game_config.cpp:54
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:50
std::vector< color_t > red_green_scale
std::string title_music
bool show_moved_orb
int combat_experience
Definition: game_config.cpp:58
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:118
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...
unsigned int tile_size
Definition: game_config.cpp:68
unsigned lobby_refresh
Definition: game_config.cpp:88
const color_range & color_info(const std::string &name)
Standard logging facilities (interface).
double hex_brightening
Definition: game_config.cpp:80
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
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
mock_char c
std::string wml_menu
std::map< std::string, t_string > team_rgb_name
std::string game_has_begun
std::string grid_top
std::string fog_prefix
Definition: game_config.cpp:71
std::vector< server_info > server_list
Definition: game_config.cpp:94
std::string app_icon
std::string wesnoth_program_dir
Definition: game_config.cpp:48
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:90
const std::string checkbox_release
int cache_compression_level
Definition: game_config.cpp:85