mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-01 12:33:24 +00:00
403 lines
12 KiB
C++
403 lines
12 KiB
C++
/*
|
|
Copyright (C) 2003 - 2014 by David White <dave@whitevine.net>
|
|
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY.
|
|
|
|
See the COPYING file for more details.
|
|
*/
|
|
|
|
#include "global.hpp"
|
|
#include "game_config.hpp"
|
|
|
|
#include "color_range.hpp"
|
|
#include "config.hpp"
|
|
#include "gettext.hpp"
|
|
#include "log.hpp"
|
|
#include "util.hpp"
|
|
#include "version.hpp"
|
|
#include "wesconfig.h"
|
|
#include "serialization/string_utils.hpp"
|
|
#ifdef LOAD_REVISION
|
|
#include "revision.h"
|
|
#endif
|
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
static lg::log_domain log_engine("engine");
|
|
#define DBG_NG LOG_STREAM(debug, log_engine)
|
|
#define ERR_NG LOG_STREAM(err, log_engine)
|
|
|
|
namespace game_config
|
|
{
|
|
int base_income = 2;
|
|
int village_income = 1;
|
|
int village_support = 1;
|
|
int poison_amount= 8;
|
|
int rest_heal_amount= 2;
|
|
int recall_cost = 20;
|
|
int kill_experience = 8;
|
|
int tile_size = 72;
|
|
unsigned lobby_network_timer = 100;
|
|
unsigned lobby_refresh = 4000;
|
|
const int gold_carryover_percentage = 80;
|
|
const std::string version = VERSION;
|
|
std::string default_terrain;
|
|
#ifdef REVISION
|
|
const std::string revision = VERSION " (" REVISION ")";
|
|
#elif defined(VCS_SHORT_HASH) && defined(VCS_WC_MODIFIED)
|
|
const std::string revision
|
|
= std::string(VERSION) + " ("
|
|
+ VCS_SHORT_HASH + (VCS_WC_MODIFIED ? "-Modified" : "-Clean") + ")";
|
|
#else
|
|
const std::string revision = VERSION;
|
|
#endif
|
|
std::string wesnoth_program_dir;
|
|
bool debug = false, debug_lua = false, editor = false,
|
|
ignore_replay_errors = false, mp_debug = false, exit_at_end = false,
|
|
no_delay = false, disable_autosave = false;
|
|
|
|
int cache_compression_level = 6;
|
|
|
|
int title_logo_x = 0, title_logo_y = 0, title_buttons_x = 0, title_buttons_y = 0, title_buttons_padding = 0,
|
|
title_tip_x = 0, title_tip_width = 0, title_tip_padding = 0;
|
|
|
|
std::string title_music,
|
|
lobby_music,
|
|
default_victory_music,
|
|
default_defeat_music;
|
|
|
|
namespace colors {
|
|
std::string moved_orb_color,
|
|
unmoved_orb_color,
|
|
partial_orb_color,
|
|
enemy_orb_color,
|
|
ally_orb_color;
|
|
}
|
|
|
|
bool show_ally_orb, show_enemy_orb, show_moved_orb, show_partial_orb, show_unmoved_orb;
|
|
|
|
namespace images {
|
|
std::string game_title,
|
|
game_title_background,
|
|
// orbs and hp/xp bar
|
|
orb,
|
|
energy,
|
|
// flags
|
|
flag,
|
|
flag_icon,
|
|
// hex overlay
|
|
terrain_mask,
|
|
grid_top,
|
|
grid_bottom,
|
|
mouseover,
|
|
selected,
|
|
editor_brush,
|
|
unreachable,
|
|
linger,
|
|
// GUI elements
|
|
observer,
|
|
tod_bright,
|
|
tod_dark,
|
|
///@todo de-hardcode this
|
|
selected_menu = "buttons/radiobox-pressed.png",
|
|
deselected_menu = "buttons/radiobox.png",
|
|
checked_menu = "buttons/checkbox-pressed.png",
|
|
unchecked_menu = "buttons/checkbox.png",
|
|
wml_menu = "buttons/WML-custom.png",
|
|
level,
|
|
ellipsis,
|
|
missing;
|
|
} //images
|
|
|
|
std::string shroud_prefix, fog_prefix;
|
|
|
|
std::string flag_rgb;
|
|
std::vector<Uint32> red_green_scale;
|
|
std::vector<Uint32> red_green_scale_text;
|
|
|
|
std::vector<Uint32> blue_white_scale;
|
|
std::vector<Uint32> blue_white_scale_text;
|
|
|
|
double hp_bar_scaling = 0.666;
|
|
double xp_bar_scaling = 0.5;
|
|
|
|
double hex_brightening = 1.25;
|
|
|
|
std::vector<std::string> foot_speed_prefix;
|
|
std::string foot_teleport_enter;
|
|
std::string foot_teleport_exit;
|
|
|
|
std::map<std::string, color_range > team_rgb_range;
|
|
std::map<std::string, t_string > team_rgb_name;
|
|
|
|
std::map<std::string, std::vector<Uint32> > team_rgb_colors;
|
|
|
|
const version_info wesnoth_version(VERSION);
|
|
const version_info min_savegame_version(MIN_SAVEGAME_VERSION);
|
|
const version_info test_version("test");
|
|
|
|
const std::string observer_team_name = "observer";
|
|
|
|
const size_t max_loop = 65536;
|
|
|
|
namespace sounds {
|
|
const std::string turn_bell = "bell.wav",
|
|
timer_bell = "timer.wav",
|
|
receive_message = "chat-[1~3].ogg",
|
|
receive_message_highlight = "chat-highlight.ogg",
|
|
receive_message_friend = "chat-friend.ogg",
|
|
receive_message_server = "receive.wav",
|
|
user_arrive = "arrive.wav",
|
|
user_leave = "leave.wav",
|
|
game_user_arrive = "join.wav",
|
|
game_user_leave = "leave.wav",
|
|
party_full_bell = "bell.wav",
|
|
mp_game_begins = "join.wav";
|
|
|
|
const std::string button_press = "button.wav",
|
|
checkbox_release = "checkbox.wav",
|
|
slider_adjust = "slider.wav",
|
|
menu_expand = "expand.wav",
|
|
menu_contract = "contract.wav",
|
|
menu_select = "select.wav";
|
|
}
|
|
|
|
#ifdef WESNOTH_PATH
|
|
std::string path = WESNOTH_PATH;
|
|
#else
|
|
std::string path = "";
|
|
#endif
|
|
|
|
#ifdef DEFAULT_PREFS_PATH
|
|
std::string default_preferences_path = DEFAULT_PREFS_PATH;
|
|
#else
|
|
std::string default_preferences_path = "";
|
|
#endif
|
|
|
|
std::vector<server_info> server_list;
|
|
|
|
void load_config(const config &v)
|
|
{
|
|
base_income = v["base_income"].to_int(2);
|
|
village_income = v["village_income"].to_int(1);
|
|
village_support = v["village_support"].to_int(1);
|
|
poison_amount = v["poison_amount"].to_int(8);
|
|
rest_heal_amount = v["rest_heal_amount"].to_int(2);
|
|
recall_cost = v["recall_cost"].to_int(20);
|
|
kill_experience = v["kill_experience"].to_int(8);
|
|
lobby_refresh = v["lobby_refresh"].to_int(2000);
|
|
default_terrain = v["default_terrain"].str();
|
|
tile_size = v["tile_size"].to_int(72);
|
|
|
|
title_music = v["title_music"].str();
|
|
lobby_music = v["lobby_music"].str();
|
|
default_victory_music = v["default_victory_music"].str();
|
|
default_defeat_music = v["default_defeat_music"].str();
|
|
|
|
if(const config &i = v.child("colors")){
|
|
using namespace game_config::colors;
|
|
moved_orb_color = i["moved_orb_color"].str();
|
|
unmoved_orb_color = i["unmoved_orb_color"].str();
|
|
partial_orb_color = i["partial_orb_color"].str();
|
|
enemy_orb_color = i["enemy_orb_color"].str();
|
|
ally_orb_color = i["ally_orb_color"].str();
|
|
} // colors
|
|
|
|
show_ally_orb = v["show_ally_orb"].to_bool(true);
|
|
show_enemy_orb = v["show_enemy_orb"].to_bool(false);
|
|
show_moved_orb = v["show_moved_orb"].to_bool(true);
|
|
show_partial_orb = v["show_partly_orb"].to_bool(true);
|
|
show_unmoved_orb = v["show_unmoved_orb"].to_bool(true);
|
|
|
|
if(const config &i = v.child("images")){
|
|
using namespace game_config::images;
|
|
game_title = i["game_title"].str();
|
|
game_title_background = i["game_title_background"].str();
|
|
|
|
orb = i["orb"].str();
|
|
energy = i["energy"].str();
|
|
|
|
flag = i["flag"].str();
|
|
flag_icon = i["flag_icon"].str();
|
|
|
|
terrain_mask = i["terrain_mask"].str();
|
|
grid_top = i["grid_top"].str();
|
|
grid_bottom = i["grid_bottom"].str();
|
|
mouseover = i["mouseover"].str();
|
|
selected = i["selected"].str();
|
|
editor_brush = i["editor_brush"].str();
|
|
unreachable = i["unreachable"].str();
|
|
linger = i["linger"].str();
|
|
|
|
observer = i["observer"].str();
|
|
tod_bright = i["tod_bright"].str();
|
|
tod_dark = i["tod_dark"].str();
|
|
level = i["level"].str();
|
|
ellipsis = i["ellipsis"].str();
|
|
missing = i["missing"].str();
|
|
} // images
|
|
|
|
hp_bar_scaling = v["hp_bar_scaling"].to_double(0.666);
|
|
xp_bar_scaling = v["xp_bar_scaling"].to_double(0.5);
|
|
hex_brightening = v["hex_brightening"].to_double(1.25);
|
|
|
|
foot_speed_prefix = utils::split(v["footprint_prefix"]);
|
|
foot_teleport_enter = v["footprint_teleport_enter"].str();
|
|
foot_teleport_exit = v["footprint_teleport_exit"].str();
|
|
|
|
shroud_prefix = v["shroud_prefix"].str();
|
|
fog_prefix = v["fog_prefix"].str();
|
|
|
|
add_color_info(v);
|
|
|
|
if (const config::attribute_value *a = v.get("flag_rgb"))
|
|
flag_rgb = a->str();
|
|
|
|
std::string color_string = v["red_green_scale"].str();
|
|
if(!string2rgb(color_string, red_green_scale)) {
|
|
ERR_NG << "can't parse color string red_green_scale, ignoring: " << color_string << "\n";
|
|
}
|
|
if (red_green_scale.empty()) {
|
|
red_green_scale.push_back(0x00FFFF00);
|
|
}
|
|
|
|
color_string = v["red_green_scale_text"].str();
|
|
if(!string2rgb(color_string, red_green_scale_text)) {
|
|
ERR_NG << "can't parse color string red_green_scale_text, ignoring: " << color_string << "\n";
|
|
}
|
|
if (red_green_scale_text.empty()) {
|
|
red_green_scale_text.push_back(0x00FFFF00);
|
|
}
|
|
|
|
color_string = v["blue_white_scale"].str();
|
|
if(!string2rgb(color_string, blue_white_scale)) {
|
|
ERR_NG << "can't parse color string blue_white_scale, ignoring: " << color_string << "\n";
|
|
}
|
|
if (blue_white_scale.empty()) {
|
|
blue_white_scale.push_back(0x00FFFFFF);
|
|
}
|
|
|
|
color_string = v["blue_white_scale_text"].str();
|
|
if(!string2rgb(color_string, blue_white_scale_text)) {
|
|
ERR_NG << "can't parse color string blue_white_scale_text, ignoring: " << color_string << "\n";
|
|
}
|
|
if (blue_white_scale_text.empty()) {
|
|
blue_white_scale_text.push_back(0x00FFFFFF);
|
|
}
|
|
|
|
server_list.clear();
|
|
BOOST_FOREACH(const config &server, v.child_range("server"))
|
|
{
|
|
server_info sinf;
|
|
sinf.name = server["name"].str();
|
|
sinf.address = server["address"].str();
|
|
server_list.push_back(sinf);
|
|
}
|
|
|
|
assert(wesnoth_version.good());
|
|
assert(min_savegame_version.good());
|
|
assert(test_version.good());
|
|
}
|
|
|
|
void add_color_info(const config &v)
|
|
{
|
|
BOOST_FOREACH(const config &teamC, v.child_range("color_range"))
|
|
{
|
|
const config::attribute_value *a1 = teamC.get("id"),
|
|
*a2 = teamC.get("rgb");
|
|
if (!a1 || !a2) continue;
|
|
std::string id = *a1;
|
|
std::vector<Uint32> temp;
|
|
if(!string2rgb(*a2, temp)) {
|
|
std::stringstream ss;
|
|
ss << "can't parse color string:\n" << teamC.debug() << "\n";
|
|
throw config::error(ss.str());
|
|
}
|
|
team_rgb_range.insert(std::make_pair(id,color_range(temp)));
|
|
team_rgb_name[id] = teamC["name"];
|
|
//generate palette of same name;
|
|
std::vector<Uint32> tp = palette(team_rgb_range[id]);
|
|
if (tp.empty()) continue;
|
|
team_rgb_colors.insert(std::make_pair(id,tp));
|
|
//if this is being used, output log of palette for artists use.
|
|
DBG_NG << "color palette creation:\n";
|
|
std::ostringstream str;
|
|
str << id << " = ";
|
|
for (std::vector<Uint32>::const_iterator r = tp.begin(),
|
|
r_end = tp.end(), r_beg = r; r != r_end; ++r)
|
|
{
|
|
int red = ((*r) & 0x00FF0000) >> 16;
|
|
int green = ((*r) & 0x0000FF00) >> 8;
|
|
int blue = ((*r) & 0x000000FF);
|
|
if (r != r_beg) str << ',';
|
|
str << red << ',' << green << ',' << blue;
|
|
}
|
|
DBG_NG << str.str() << '\n';
|
|
}
|
|
|
|
BOOST_FOREACH(const config &cp, v.child_range("color_palette"))
|
|
{
|
|
BOOST_FOREACH(const config::attribute &rgb, cp.attribute_range())
|
|
{
|
|
std::vector<Uint32> temp;
|
|
if(!string2rgb(rgb.second, temp)) {
|
|
ERR_NG << "Invalid color palette: " << rgb.second << "\n";
|
|
}
|
|
team_rgb_colors.insert(std::make_pair(rgb.first, temp));
|
|
}
|
|
}
|
|
}
|
|
|
|
const color_range& color_info(const std::string& name)
|
|
{
|
|
std::map<std::string, color_range>::const_iterator i = team_rgb_range.find(name);
|
|
if(i == team_rgb_range.end()) {
|
|
std::vector<Uint32> temp;
|
|
if(!string2rgb(name, temp))
|
|
throw config::error(_("Invalid color range: ") + name);
|
|
team_rgb_range.insert(std::make_pair(name,color_range(temp)));
|
|
return color_info(name);
|
|
}
|
|
return i->second;
|
|
}
|
|
|
|
const std::vector<Uint32>& tc_info(const std::string& name)
|
|
{
|
|
std::map<std::string, std::vector<Uint32> >::const_iterator i = team_rgb_colors.find(name);
|
|
if(i == team_rgb_colors.end()) {
|
|
std::vector<Uint32> temp;
|
|
if(!string2rgb(name, temp)) {
|
|
static std::vector<Uint32> stv;
|
|
ERR_NG << "Invalid color palette: " << name << "\n";
|
|
return stv;
|
|
}
|
|
team_rgb_colors.insert(std::make_pair(name,temp));
|
|
return tc_info(name);
|
|
}
|
|
return i->second;
|
|
}
|
|
|
|
Uint32 red_to_green(int val, bool for_text){
|
|
const std::vector<Uint32>& color_scale =
|
|
for_text ? red_green_scale_text : red_green_scale;
|
|
val = std::max<int>(0, std::min<int>(val, 100));
|
|
int lvl = (color_scale.size()-1) * val / 100;
|
|
return color_scale[lvl];
|
|
}
|
|
|
|
Uint32 blue_to_white(int val, bool for_text){
|
|
const std::vector<Uint32>& color_scale =
|
|
for_text ? blue_white_scale_text : blue_white_scale;
|
|
val = std::max<int>(0, std::min<int>(val, 100));
|
|
int lvl = (color_scale.size()-1) * val / 100;
|
|
return color_scale[lvl];
|
|
}
|
|
|
|
} // game_config
|