Merge branch 'master' of https://github.com/wesnoth/wesnoth
This commit is contained in:
commit
3c091dbe7d
18 changed files with 149 additions and 124 deletions
|
@ -6,6 +6,7 @@ Version 1.13.2+dev:
|
|||
in a couple of places so Wesnoth does not quit on startup when trying to
|
||||
relocate the log file to a path with Unicode characters (bug #22897,
|
||||
definitely fixed this time).
|
||||
* Fix bug #23108: exclude aborted attacks from statistics
|
||||
|
||||
Version 1.13.2:
|
||||
* Add-ons client:
|
||||
|
|
|
@ -27,17 +27,6 @@
|
|||
[event]
|
||||
name=prestart
|
||||
|
||||
#ifdef DEBUG_MODE
|
||||
[set_menu_item]
|
||||
description="let kalenz arrive" #wmllint: ignore
|
||||
[command]
|
||||
[fire_event]
|
||||
name=kalenz_arrives
|
||||
[/fire_event]
|
||||
[/command]
|
||||
[/set_menu_item]
|
||||
#endif
|
||||
|
||||
[replace_map]
|
||||
x=9-53
|
||||
y=9-53
|
||||
|
|
|
@ -1299,6 +1299,9 @@
|
|||
name = "Paŭlo Ebermann (Pauxlo)"
|
||||
wikiuser = "Pauxlo"
|
||||
[/entry]
|
||||
[entry]
|
||||
name = "Peter Elmers"
|
||||
[/entry]
|
||||
[entry]
|
||||
name = "Peter Mawhorter (solsword)"
|
||||
wikiuser = "solsword"
|
||||
|
|
|
@ -10,17 +10,15 @@
|
|||
#enddef
|
||||
|
||||
#define COLOR_HEAL
|
||||
green=255
|
||||
color="0,255,0"
|
||||
#enddef
|
||||
|
||||
#define COLOR_HARM
|
||||
red=255
|
||||
color="255,0,0"
|
||||
#enddef
|
||||
|
||||
#define COLOR_WHITE
|
||||
red=255
|
||||
green=255
|
||||
blue=255
|
||||
color="255,255,255"
|
||||
#enddef
|
||||
|
||||
#define IS_HERO
|
||||
|
|
|
@ -725,6 +725,12 @@ namespace {
|
|||
std::string dump();
|
||||
};
|
||||
|
||||
/**
|
||||
* Used in perform_hit to confirm a replay is in sync.
|
||||
* Check OOS_error_ after this method, true if error detected.
|
||||
*/
|
||||
void check_replay_attack_result(bool, int, int, config, unit_info&);
|
||||
|
||||
void unit_killed(unit_info &, unit_info &,
|
||||
const battle_context_unit_stats *&, const battle_context_unit_stats *&,
|
||||
bool);
|
||||
|
@ -901,7 +907,6 @@ namespace {
|
|||
resources::gamedata->get_variable("damage_inflicted") = damage;
|
||||
}
|
||||
|
||||
|
||||
// Make sure that if we're serializing a game here,
|
||||
// we got the same results as the game did originally.
|
||||
const config local_results = config_of("chance", attacker.cth_)("hits", hits)("damage", damage);
|
||||
|
@ -909,62 +914,18 @@ namespace {
|
|||
bool equals_replay = checkup_instance->local_checkup(local_results, replay_results);
|
||||
if (!equals_replay)
|
||||
{
|
||||
|
||||
int results_chance = replay_results["chance"];
|
||||
bool results_hits = replay_results["hits"].to_bool();
|
||||
int results_damage = replay_results["damage"];
|
||||
/*
|
||||
errbuf_ << "SYNC: In attack " << a_.dump() << " vs " << d_.dump()
|
||||
<< " replay data differs from local calculated data:"
|
||||
<< " chance to hit in data source: " << results_chance
|
||||
<< " chance to hit in calculated: " << attacker.cth_
|
||||
<< " chance to hit in data source: " << results_chance
|
||||
<< " chance to hit in calculated: " << attacker.cth_
|
||||
;
|
||||
|
||||
attacker.cth_ = results_chance;
|
||||
hits = results_hits;
|
||||
damage = results_damage;
|
||||
|
||||
OOS_error_ = true;
|
||||
*/
|
||||
if (results_chance != attacker.cth_)
|
||||
{
|
||||
errbuf_ << "SYNC: In attack " << a_.dump() << " vs " << d_.dump()
|
||||
<< ": chance to hit is inconsistent. Data source: "
|
||||
<< results_chance << "; Calculation: " << attacker.cth_
|
||||
<< " (over-riding game calculations with data source results)\n";
|
||||
attacker.cth_ = results_chance;
|
||||
OOS_error_ = true;
|
||||
}
|
||||
|
||||
if (results_hits != hits)
|
||||
{
|
||||
errbuf_ << "SYNC: In attack " << a_.dump() << " vs " << d_.dump()
|
||||
<< ": the data source says the hit was "
|
||||
<< (results_hits ? "successful" : "unsuccessful")
|
||||
<< ", while in-game calculations say the hit was "
|
||||
<< (hits ? "successful" : "unsuccessful")
|
||||
<< " random number: " << ran_num << " = "
|
||||
<< (ran_num % 100) << "/" << results_chance
|
||||
<< " (over-riding game calculations with data source results)\n";
|
||||
hits = results_hits;
|
||||
OOS_error_ = true;
|
||||
}
|
||||
|
||||
if (results_damage != damage)
|
||||
{
|
||||
errbuf_ << "SYNC: In attack " << a_.dump() << " vs " << d_.dump()
|
||||
<< ": the data source says the hit did " << results_damage
|
||||
<< " damage, while in-game calculations show the hit doing "
|
||||
<< damage
|
||||
<< " damage (over-riding game calculations with data source results)\n";
|
||||
damage = results_damage;
|
||||
OOS_error_ = true;
|
||||
}
|
||||
check_replay_attack_result(hits, ran_num, damage, replay_results, attacker);
|
||||
}
|
||||
|
||||
// can do no more damage than the defender has hitpoints
|
||||
int damage_done = std::min<int>(defender.get_unit().hitpoints(), attacker.damage_);
|
||||
// expected damage = damage potential * chance to hit (as a percentage)
|
||||
double expected_damage = damage_done*attacker.cth_*0.01;
|
||||
if (attacker_turn) {
|
||||
stats.attack_expected_damage(expected_damage, 0);
|
||||
} else {
|
||||
stats.attack_expected_damage(0, expected_damage);
|
||||
}
|
||||
|
||||
int drains_damage = 0;
|
||||
if (hits && attacker_stats->drains) {
|
||||
|
@ -1262,17 +1223,6 @@ namespace {
|
|||
DBG_NG << "getting attack statistics\n";
|
||||
statistics::attack_context attack_stats(a_.get_unit(), d_.get_unit(), a_stats_->chance_to_hit, d_stats_->chance_to_hit);
|
||||
|
||||
{
|
||||
// Calculate stats for battle
|
||||
combatant attacker(bc_->get_attacker_stats());
|
||||
combatant defender(bc_->get_defender_stats());
|
||||
attacker.fight(defender,false);
|
||||
const double attacker_inflict = static_cast<double>(d_.get_unit().hitpoints()) - defender.average_hp();
|
||||
const double defender_inflict = static_cast<double>(a_.get_unit().hitpoints()) - attacker.average_hp();
|
||||
|
||||
attack_stats.attack_expected_damage(attacker_inflict,defender_inflict);
|
||||
}
|
||||
|
||||
a_.orig_attacks_ = a_stats_->num_blows;
|
||||
d_.orig_attacks_ = d_stats_->num_blows;
|
||||
a_.n_attacks_ = a_.orig_attacks_;
|
||||
|
@ -1301,7 +1251,10 @@ namespace {
|
|||
++abs_n_attack_;
|
||||
|
||||
if (a_.n_attacks_ > 0 && !defender_strikes_first) {
|
||||
if (!perform_hit(true, attack_stats)) break;
|
||||
if (!perform_hit(true, attack_stats)) {
|
||||
DBG_NG << "broke from attack loop on attacker turn\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If the defender got to strike first, they use it up here.
|
||||
|
@ -1309,7 +1262,10 @@ namespace {
|
|||
++abs_n_defend_;
|
||||
|
||||
if (d_.n_attacks_ > 0) {
|
||||
if (!perform_hit(false, attack_stats)) break;
|
||||
if (!perform_hit(false, attack_stats)) {
|
||||
DBG_NG << "broke from attack loop on defender turn\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Continue the fight to death; if one of the units got petrified,
|
||||
|
@ -1365,8 +1321,63 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
} //end anonymous namespace
|
||||
void attack::check_replay_attack_result(bool hits, int ran_num, int damage,
|
||||
config replay_results, unit_info& attacker)
|
||||
{
|
||||
int results_chance = replay_results["chance"];
|
||||
bool results_hits = replay_results["hits"].to_bool();
|
||||
int results_damage = replay_results["damage"];
|
||||
/*
|
||||
errbuf_ << "SYNC: In attack " << a_.dump() << " vs " << d_.dump()
|
||||
<< " replay data differs from local calculated data:"
|
||||
<< " chance to hit in data source: " << results_chance
|
||||
<< " chance to hit in calculated: " << attacker.cth_
|
||||
<< " chance to hit in data source: " << results_chance
|
||||
<< " chance to hit in calculated: " << attacker.cth_
|
||||
;
|
||||
|
||||
attacker.cth_ = results_chance;
|
||||
hits = results_hits;
|
||||
damage = results_damage;
|
||||
|
||||
OOS_error_ = true;
|
||||
*/
|
||||
if (results_chance != attacker.cth_)
|
||||
{
|
||||
errbuf_ << "SYNC: In attack " << a_.dump() << " vs " << d_.dump()
|
||||
<< ": chance to hit is inconsistent. Data source: "
|
||||
<< results_chance << "; Calculation: " << attacker.cth_
|
||||
<< " (over-riding game calculations with data source results)\n";
|
||||
attacker.cth_ = results_chance;
|
||||
OOS_error_ = true;
|
||||
}
|
||||
|
||||
if (results_hits != hits)
|
||||
{
|
||||
errbuf_ << "SYNC: In attack " << a_.dump() << " vs " << d_.dump()
|
||||
<< ": the data source says the hit was "
|
||||
<< (results_hits ? "successful" : "unsuccessful")
|
||||
<< ", while in-game calculations say the hit was "
|
||||
<< (hits ? "successful" : "unsuccessful")
|
||||
<< " random number: " << ran_num << " = "
|
||||
<< (ran_num % 100) << "/" << results_chance
|
||||
<< " (over-riding game calculations with data source results)\n";
|
||||
hits = results_hits;
|
||||
OOS_error_ = true;
|
||||
}
|
||||
|
||||
if (results_damage != damage)
|
||||
{
|
||||
errbuf_ << "SYNC: In attack " << a_.dump() << " vs " << d_.dump()
|
||||
<< ": the data source says the hit did " << results_damage
|
||||
<< " damage, while in-game calculations show the hit doing "
|
||||
<< damage
|
||||
<< " damage (over-riding game calculations with data source results)\n";
|
||||
damage = results_damage;
|
||||
OOS_error_ = true;
|
||||
}
|
||||
}
|
||||
} //end anonymous namespace
|
||||
|
||||
void attack_unit(const map_location &attacker, const map_location &defender,
|
||||
int attack_with, int defend_with, bool update_display)
|
||||
|
@ -1376,7 +1387,6 @@ void attack_unit(const map_location &attacker, const map_location &defender,
|
|||
}
|
||||
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
class unit_advancement_choice : public mp_sync::user_choice
|
||||
|
|
|
@ -261,7 +261,7 @@ private:
|
|||
}
|
||||
|
||||
void display_float(const map_location& location, const std::string& text) const{
|
||||
game_display::get_singleton()->float_label(location,text,255,0,0);
|
||||
game_display::get_singleton()->float_label(location, text, create_color(255,0,0));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -728,8 +728,7 @@ void game_display::set_route(const pathfind::marked_route *route)
|
|||
invalidate_route();
|
||||
}
|
||||
|
||||
void game_display::float_label(const map_location& loc, const std::string& text,
|
||||
int red, int green, int blue)
|
||||
void game_display::float_label(const map_location& loc, const std::string& text, const SDL_Color& color)
|
||||
{
|
||||
if(preferences::show_floating_labels() == false || fogged(loc)) {
|
||||
return;
|
||||
|
@ -737,7 +736,6 @@ void game_display::float_label(const map_location& loc, const std::string& text,
|
|||
|
||||
font::floating_label flabel(text);
|
||||
flabel.set_font_size(font::SIZE_XLARGE);
|
||||
const SDL_Color color = create_color(red, green, blue);
|
||||
flabel.set_color(color);
|
||||
flabel.set_position(get_location_x(loc)+zoom_/2, get_location_y(loc));
|
||||
flabel.set_move(0, -2 * turbo_speed());
|
||||
|
|
|
@ -116,8 +116,7 @@ public:
|
|||
void set_route(const pathfind::marked_route *route);
|
||||
|
||||
/** Function to float a label above a tile */
|
||||
void float_label(const map_location& loc, const std::string& text,
|
||||
int red, int green, int blue);
|
||||
void float_label(const map_location& loc, const std::string& text, const SDL_Color& color);
|
||||
|
||||
/** Draws the movement info (turns available) for a given location. */
|
||||
void draw_movement_info(const map_location& loc);
|
||||
|
|
|
@ -84,6 +84,7 @@ static lg::log_domain log_display("display");
|
|||
|
||||
static lg::log_domain log_wml("wml");
|
||||
#define LOG_WML LOG_STREAM(info, log_wml)
|
||||
#define WRN_WML LOG_STREAM(warn, log_wml)
|
||||
#define ERR_WML LOG_STREAM(err, log_wml)
|
||||
|
||||
static lg::log_domain log_config("config");
|
||||
|
@ -1342,7 +1343,15 @@ WML_HANDLER_FUNCTION(unstore_unit, /*event_info*/, cfg)
|
|||
if(!text.empty() && !controller->is_skipping_replay())
|
||||
{
|
||||
// Print floating label
|
||||
resources::screen->float_label(loc, text, cfg["red"], cfg["green"], cfg["blue"]);
|
||||
SDL_Color color = font::LABEL_COLOR;
|
||||
|
||||
if(!cfg["color"].empty()) {
|
||||
color = string_to_color(cfg["color"]);
|
||||
} else if(cfg.has_attribute("red") || cfg.has_attribute("green") || cfg.has_attribute("blue")) {
|
||||
color = create_color(cfg["red"], cfg["green"], cfg["blue"]);
|
||||
}
|
||||
|
||||
resources::screen->float_label(loc, text, color);
|
||||
}
|
||||
if(advance) {
|
||||
advance_unit_at(advance_unit_params(loc)
|
||||
|
|
|
@ -991,11 +991,7 @@ config side_engine::new_config() const
|
|||
|
||||
// Save default "recruit" so that correct faction lists would be
|
||||
// initialized by flg_manager when the new side config is sent over network.
|
||||
// In case recruit list was empty, set a flag to indicate that.
|
||||
res["default_recruit"] = cfg_["recruit"].str();
|
||||
if (res["default_recruit"].empty()) {
|
||||
res["no_recruit"] = true;
|
||||
}
|
||||
|
||||
// If the user is allowed to change type, faction, leader etc,
|
||||
// then import their new values in the config.
|
||||
|
|
|
@ -578,27 +578,30 @@ void create_engine::prepare_for_campaign(const std::string& difficulty)
|
|||
*
|
||||
* @param set_value Preselected difficulty number. The default -1 launches the gui.
|
||||
* @return Selected difficulty. Returns "FAIL" if set_value is invalid,
|
||||
* and "CANCEL" if the gui is cancelled.
|
||||
* and "CANCEL" if the gui is canceled.
|
||||
*/
|
||||
std::string create_engine::select_campaign_difficulty(int set_value)
|
||||
{
|
||||
// Verify the existence of difficulties
|
||||
std::vector<std::string> difficulties;
|
||||
|
||||
BOOST_FOREACH(const config &d, current_level().data().child_range("difficulty"))
|
||||
{
|
||||
difficulties.push_back(d["define"]);
|
||||
}
|
||||
|
||||
if(difficulties.empty()) {
|
||||
difficulties = utils::split(current_level().data()["difficulties"]);
|
||||
}
|
||||
|
||||
// No difficulties found. Exit
|
||||
if(difficulties.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// A specific difficulty value was passed
|
||||
// Use a minimilistic interface to get the specified define
|
||||
if(set_value != -1) {
|
||||
std::vector<std::string> difficulties =
|
||||
utils::split(current_level().data()["difficulties"]);
|
||||
|
||||
if(difficulties.empty()) {
|
||||
BOOST_FOREACH(const config &d, current_level().data().child_range("difficulty"))
|
||||
{
|
||||
difficulties.push_back(d["define"]);
|
||||
}
|
||||
}
|
||||
|
||||
if(difficulties.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (set_value > static_cast<int>(difficulties.size())) {
|
||||
std::cerr << "incorrect difficulty number: [" <<
|
||||
set_value << "]. maximum is [" << difficulties.size() << "].\n";
|
||||
|
@ -613,6 +616,8 @@ std::string create_engine::select_campaign_difficulty(int set_value)
|
|||
}
|
||||
|
||||
// If not, let the user pick one from the prompt
|
||||
// We don't pass the difficulties vector here because additional data is required
|
||||
// to constrict the dialog
|
||||
gui2::tcampaign_difficulty dlg(current_level().data());
|
||||
dlg.show(disp_.video());
|
||||
|
||||
|
|
|
@ -625,7 +625,7 @@ void flg_manager::set_current_gender(const std::string& gender)
|
|||
|
||||
std::vector<std::string> flg_manager::get_original_recruits(const config& cfg)
|
||||
{
|
||||
if (cfg["no_recruit"].to_bool()) {
|
||||
if (cfg["default_recruit"].empty()) {
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
const config::attribute_value& cfg_default_recruit = cfg["default_recruit"];
|
||||
|
|
|
@ -288,7 +288,7 @@ void help_text_area::handle_format_cfg(const config &cfg)
|
|||
bool bold = cfg["bold"].to_bool();
|
||||
bool italic = cfg["italic"].to_bool();
|
||||
int font_size = cfg["font_size"].to_int(normal_font_size);
|
||||
SDL_Color color = string_to_color(cfg["color"]);
|
||||
SDL_Color color = help::string_to_color(cfg["color"]);
|
||||
add_text_item(text, "", false, font_size, bold, italic, color);
|
||||
}
|
||||
|
||||
|
|
|
@ -398,11 +398,9 @@ void terrain_label::read(const config &cfg)
|
|||
tmp_color = utils::interpolate_variables_into_string(tmp_color, vs);
|
||||
|
||||
if(!tmp_color.empty()) {
|
||||
std::vector<Uint32> temp_rgb;
|
||||
if(string2rgb(tmp_color, temp_rgb) && !temp_rgb.empty()) {
|
||||
color = int_to_color(temp_rgb[0]);
|
||||
}
|
||||
color = string_to_color(tmp_color);
|
||||
}
|
||||
|
||||
color_ = color;
|
||||
}
|
||||
|
||||
|
|
|
@ -2255,7 +2255,14 @@ int game_lua_kernel::intf_print(lua_State *L) {
|
|||
|
||||
int size = cfg["size"].to_int(font::SIZE_SMALL);
|
||||
int lifetime = cfg["duration"].to_int(50);
|
||||
SDL_Color color = create_color(cfg["red"], cfg["green"], cfg["blue"]);
|
||||
|
||||
SDL_Color color = font::LABEL_COLOR;
|
||||
|
||||
if(!cfg["color"].empty()) {
|
||||
color = string_to_color(cfg["color"]);
|
||||
} else if(cfg.has_attribute("red") || cfg.has_attribute("green") || cfg.has_attribute("blue")) {
|
||||
color = create_color(cfg["red"], cfg["green"], cfg["blue"]);
|
||||
}
|
||||
|
||||
const SDL_Rect& rect = game_display_->map_outside_area();
|
||||
|
||||
|
@ -2517,8 +2524,7 @@ int game_lua_kernel::intf_float_label(lua_State *L)
|
|||
|
||||
t_string text = luaW_checktstring(L, 3);
|
||||
if (game_display_) {
|
||||
game_display_->float_label(loc, text, font::LABEL_COLOR.r,
|
||||
font::LABEL_COLOR.g, font::LABEL_COLOR.b);
|
||||
game_display_->float_label(loc, text, font::LABEL_COLOR);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "global.hpp"
|
||||
#include "color_range.hpp"
|
||||
|
||||
#include "sdl/utils.hpp"
|
||||
#include "sdl/alpha.hpp"
|
||||
|
@ -75,6 +76,18 @@ SDL_Color int_to_color(const Uint32 rgb)
|
|||
return result;
|
||||
}
|
||||
|
||||
SDL_Color string_to_color(const std::string& color_string)
|
||||
{
|
||||
SDL_Color color;
|
||||
|
||||
std::vector<Uint32> temp_rgb;
|
||||
if(string2rgb(color_string, temp_rgb) && !temp_rgb.empty()) {
|
||||
color = int_to_color(temp_rgb[0]);
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
SDL_Color create_color(const unsigned char red
|
||||
, unsigned char green
|
||||
, unsigned char blue
|
||||
|
|
|
@ -432,8 +432,10 @@ SDL_Rect get_non_transparent_portion(const surface &surf);
|
|||
|
||||
bool operator==(const SDL_Color& a, const SDL_Color& b);
|
||||
bool operator!=(const SDL_Color& a, const SDL_Color& b);
|
||||
|
||||
SDL_Color inverse(const SDL_Color& color);
|
||||
SDL_Color int_to_color(const Uint32 rgb);
|
||||
SDL_Color string_to_color(const std::string& color_string);
|
||||
|
||||
SDL_Color create_color(const unsigned char red
|
||||
, unsigned char green
|
||||
|
|
|
@ -649,10 +649,8 @@ void unit_frame::redraw(const int frame_time,bool on_start_time,bool in_scope_of
|
|||
sound::play_sound(current_data.sound);
|
||||
}
|
||||
if(!current_data.text.empty() ) {
|
||||
game_display::get_singleton()->float_label(src,current_data.text,
|
||||
(current_data.text_color & 0x00FF0000) >> 16,
|
||||
(current_data.text_color & 0x0000FF00) >> 8,
|
||||
(current_data.text_color & 0x000000FF) >> 0);
|
||||
game_display::get_singleton()->float_label(src, current_data.text,
|
||||
int_to_color(current_data.text_color));
|
||||
}
|
||||
}
|
||||
image::locator image_loc;
|
||||
|
|
Loading…
Add table
Reference in a new issue