The Battle for Wesnoth  1.15.2+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 // 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
175 
176 } // colors
177 
178 //
179 // Image constants
180 //
181 std::vector<std::string> foot_speed_prefix;
182 
184 std::string foot_teleport_exit;
185 
186 namespace images {
187 
188 std::string
191  game_logo,
196  // orbs and hp/xp bar
197  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 config& v, bool build_defaults);
272 void add_color_info(const config& v)
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  } // colors
314 
315  show_ally_orb = v["show_ally_orb"].to_bool(true);
316  show_enemy_orb = v["show_enemy_orb"].to_bool(false);
317  show_moved_orb = v["show_moved_orb"].to_bool(true);
318  show_partial_orb = v["show_partly_orb"].to_bool(true);
319  show_unmoved_orb = v["show_unmoved_orb"].to_bool(true);
320 
321  if(const config& i = v.child("images")){
322  using namespace game_config::images;
323 
324  game_title = i["game_title"].str();
325  game_title_background = i["game_title_background"].str();
326  game_logo = i["game_logo"].str();
327  game_logo_background = i["game_logo_background"].str();
328 
329  victory_laurel = i["victory_laurel"].str();
330  victory_laurel_hardest = i["victory_laurel_hardest"].str();
331  victory_laurel_easy = i["victory_laurel_easy"].str();
332 
333  orb = i["orb"].str();
334  energy = i["energy"].str();
335 
336  battery_icon = i["battery_icon"].str();
337  time_icon = i["time_icon"].str();
338 
339  flag = i["flag"].str();
340  flag_icon = i["flag_icon"].str();
341 
342  terrain_mask = i["terrain_mask"].str();
343  grid_top = i["grid_top"].str();
344  grid_bottom = i["grid_bottom"].str();
345  mouseover = i["mouseover"].str();
346  selected = i["selected"].str();
347  editor_brush = i["editor_brush"].str();
348  unreachable = i["unreachable"].str();
349  linger = i["linger"].str();
350 
351  observer = i["observer"].str();
352  tod_bright = i["tod_bright"].str();
353  tod_dark = i["tod_dark"].str();
354  level = i["level"].str();
355  ellipsis = i["ellipsis"].str();
356  missing = i["missing"].str();
357  } // images
358 
359  hp_bar_scaling = v["hp_bar_scaling"].to_double(0.666);
360  xp_bar_scaling = v["xp_bar_scaling"].to_double(0.5);
361  hex_brightening = v["hex_brightening"].to_double(1.25);
362 
363  foot_speed_prefix = utils::split(v["footprint_prefix"]);
364  foot_teleport_enter = v["footprint_teleport_enter"].str();
365  foot_teleport_exit = v["footprint_teleport_exit"].str();
366 
367  shroud_prefix = v["shroud_prefix"].str();
368  fog_prefix = v["fog_prefix"].str();
369 
370  add_color_info(v, true);
371 
372  if(const config::attribute_value* a = v.get("flag_rgb")) {
373  flag_rgb = a->str();
374  }
375 
376  if(const config::attribute_value* a = v.get("unit_rgb")) {
377  unit_rgb = a->str();
378  }
379 
380  const auto parse_config_color_list = [&](
381  const std::string& key,
382  const color_t fallback)->std::vector<color_t>
383  {
384  std::vector<color_t> color_vec;
385 
386  for(const auto& s : utils::split(v[key].str())) {
387  try {
388  color_vec.push_back(color_t::from_hex_string(s));
389  } catch(const std::invalid_argument& e) {
390  ERR_NG << "Error parsing color list '" << key << "'.\n" << e.what() << std::endl;
391  color_vec.push_back(fallback);
392  }
393  }
394 
395  return color_vec;
396  };
397 
398  red_green_scale = parse_config_color_list("red_green_scale", {255, 255, 255});
399  red_green_scale_text = parse_config_color_list("red_green_scale_text", {255, 255, 255});
400  blue_white_scale = parse_config_color_list("blue_white_scale", {0 , 0 , 255});
401  blue_white_scale_text = parse_config_color_list("blue_white_scale_text", {0 , 0 , 255});
402 
403  server_list.clear();
404 
405  for(const config& server : v.child_range("server")) {
406  server_info sinf;
407  sinf.name = server["name"].str();
408  sinf.address = server["address"].str();
409  server_list.push_back(sinf);
410  }
411 
412  if(const config& s = v.child("sounds")) {
413  using namespace game_config::sounds;
414 
415  const auto load_attribute = [](const config& c, const std::string& key, std::string& member) {
416  if(c.has_attribute(key)) {
417  member = c[key].str();
418  }
419  };
420 
421  load_attribute(s, "turn_bell", turn_bell);
422  load_attribute(s, "timer_bell", timer_bell);
423  load_attribute(s, "public_message", public_message);
424  load_attribute(s, "private_message", private_message);
425  load_attribute(s, "friend_message", friend_message);
426  load_attribute(s, "server_message", server_message);
427  load_attribute(s, "player_joins", player_joins);
428  load_attribute(s, "player_leaves", player_leaves);
429  load_attribute(s, "game_created", game_created);
430  load_attribute(s, "game_user_arrive", game_user_arrive);
431  load_attribute(s, "game_user_leave", game_user_leave);
432  load_attribute(s, "ready_for_start", ready_for_start);
433  load_attribute(s, "game_has_begun", game_has_begun);
434 
435  if(const config & ss = s.child("status")) {
436  using namespace game_config::sounds::status;
437 
438  load_attribute(ss, "poisoned", poisoned);
439  load_attribute(ss, "slowed", slowed);
440  load_attribute(ss, "petrified", petrified);
441  }
442  }
443 }
444 
445 void add_color_info(const config& v, bool build_defaults)
446 {
447  if(build_defaults) {
448  default_colors.clear();
449  }
450 
451  for(const config& teamC : v.child_range("color_range")) {
452  const config::attribute_value* a1 = teamC.get("id"), *a2 = teamC.get("rgb");
453  if(!a1 || !a2) {
454  continue;
455  }
456 
457  std::string id = *a1;
458  std::vector<color_t> temp;
459 
460  for(const auto& s : utils::split(*a2)) {
461  try {
462  temp.push_back(color_t::from_hex_string(s));
463  } catch(const std::invalid_argument&) {
464  std::stringstream ss;
465  ss << "can't parse color string:\n" << teamC.debug() << "\n";
466  throw config::error(ss.str());
467  }
468  }
469 
470  team_rgb_range.emplace(id, color_range(temp));
471  team_rgb_name.emplace(id, teamC["name"].t_str());
472 
473  LOG_NG << "registered color range '" << id << "': " << team_rgb_range[id].debug() << '\n';
474 
475  // Ggenerate palette of same name;
476  std::vector<color_t> tp = palette(team_rgb_range[id]);
477  if(!tp.empty()) {
478  team_rgb_colors.emplace(id, tp);
479  }
480 
481  if(build_defaults && teamC["default"].to_bool()) {
482  default_colors.push_back(*a1);
483  }
484  }
485 
486  for(const config &cp : v.child_range("color_palette")) {
487  for(const config::attribute& rgb : cp.attribute_range()) {
488  std::vector<color_t> temp;
489  for(const auto& s : utils::split(rgb.second)) {
490  try {
491  temp.push_back(color_t::from_hex_string(s));
492  } catch(const std::invalid_argument&) {
493  ERR_NG << "Invalid color in palette: " << s << std::endl;
494  }
495  }
496 
497  team_rgb_colors.emplace(rgb.first, temp);
498  LOG_NG << "registered color palette: " << rgb.first << '\n';
499  }
500  }
501 }
502 
504 {
505  default_colors.clear();
506  team_rgb_colors.clear();
507  team_rgb_name.clear();
508  team_rgb_range.clear();
509 }
510 
511 const color_range& color_info(const std::string& name)
512 {
513  auto i = team_rgb_range.find(name);
514  if(i != team_rgb_range.end()) {
515  return i->second;
516  }
517 
518  std::vector<color_t> temp;
519  for(const auto& s : utils::split(name)) {
520  try {
521  temp.push_back(color_t::from_hex_string(s));
522  } catch(const std::invalid_argument&) {
523  throw config::error(_("Invalid color in range: ") + s);
524  }
525  }
526 
527  team_rgb_range.emplace(name, color_range(temp));
528  return color_info(name);
529 }
530 
531 const std::vector<color_t>& tc_info(const std::string& name)
532 {
533  auto i = team_rgb_colors.find(name);
534  if(i != team_rgb_colors.end()) {
535  return i->second;
536  }
537 
538  std::vector<color_t> temp;
539  for(const auto& s : utils::split(name)) {
540  try {
541  temp.push_back(color_t::from_hex_string(s));
542  } catch(const std::invalid_argument&) {
543  static std::vector<color_t> stv;
544  ERR_NG << "Invalid color in palette: " << s << std::endl;
545  return stv;
546  }
547  }
548 
549  team_rgb_colors.emplace(name, temp);
550  return tc_info(name);
551 }
552 
553 color_t red_to_green(int val, bool for_text)
554 {
555  const std::vector<color_t>& color_scale = for_text ? red_green_scale_text : red_green_scale;
556 
557  val = utils::clamp(val, 0, 100);
558  const int lvl = (color_scale.size() - 1) * val / 100;
559 
560  return color_scale[lvl];
561 }
562 
563 color_t blue_to_white(int val, bool for_text)
564 {
565  const std::vector<color_t>& color_scale = for_text ? blue_white_scale_text : blue_white_scale;
566 
567  val = utils::clamp(val, 0, 100);
568  const int lvl = (color_scale.size() - 1) * val / 100;
569 
570  return color_scale[lvl];
571 }
572 
574 {
575  std::string ret = _("The Battle for Wesnoth") + " - " + revision;
576  return ret;
577 }
578 
579 } // 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:226
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
#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
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: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:68
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