Split report generators into separate functions.
This commit is contained in:
parent
cbfa9218f5
commit
f6465949e5
7 changed files with 875 additions and 803 deletions
|
@ -342,7 +342,6 @@ set(wesnoth-main_SRC
|
|||
game_preferences.cpp
|
||||
game_preferences_display.cpp
|
||||
gamestatus.cpp
|
||||
generate_report.cpp
|
||||
generic_event.cpp
|
||||
gui/auxiliary/canvas.cpp
|
||||
gui/auxiliary/event/dispatcher.cpp
|
||||
|
|
|
@ -113,7 +113,6 @@ wesnoth_source = \
|
|||
game_preferences.cpp \
|
||||
game_preferences_display.cpp \
|
||||
gamestatus.cpp \
|
||||
generate_report.cpp \
|
||||
generic_event.cpp \
|
||||
gui/auxiliary/canvas.cpp \
|
||||
gui/auxiliary/event/dispatcher.cpp \
|
||||
|
|
|
@ -212,7 +212,6 @@ wesnoth_sources = Split("""
|
|||
game_events.cpp
|
||||
game_preferences.cpp
|
||||
gamestatus.cpp
|
||||
generate_report.cpp
|
||||
halo.cpp
|
||||
help.cpp
|
||||
intro.cpp
|
||||
|
|
|
@ -432,11 +432,13 @@ void game_display::draw_report(reports::TYPE report_num)
|
|||
return;
|
||||
}
|
||||
|
||||
reports::report report = reports::generate_report(report_num,
|
||||
teams_[viewing_team()], currentTeam_ + 1, activeTeam_ + 1,
|
||||
reports::report_data data = {
|
||||
viewing_team() + 1, currentTeam_ + 1, activeTeam_ + 1,
|
||||
selectedHex_, mouseoverHex_, displayedUnitHex_,
|
||||
observers_, level_, !viewpoint_);
|
||||
observers_, level_, !viewpoint_
|
||||
};
|
||||
|
||||
reports::report report = reports::generate_report(report_num, data);
|
||||
refresh_report(report_num, report);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,791 +0,0 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2003 - 2010 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Formatted output of various stats about units and the game.
|
||||
* Used for the right sidebar and the top line of the main game-display.
|
||||
*/
|
||||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "actions.hpp"
|
||||
#include "font.hpp"
|
||||
#include "foreach.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "language.hpp"
|
||||
#include "map.hpp"
|
||||
#include "marked-up_text.hpp"
|
||||
#include "reports.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "team.hpp"
|
||||
#include "tod_manager.hpp"
|
||||
#include "whiteboard/manager.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
|
||||
#ifndef DISABLE_EDITOR
|
||||
namespace editor {
|
||||
extern std::string selected_terrain, left_button_function;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace reports {
|
||||
|
||||
static void add_status(report &r,
|
||||
char const *path, char const *desc1, char const *desc2)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << gettext(desc1) << gettext(desc2);
|
||||
r.add_image(path, s.str());
|
||||
}
|
||||
|
||||
static std::string flush(std::ostringstream &s)
|
||||
{
|
||||
std::string r(s.str());
|
||||
s.str(std::string());
|
||||
return r;
|
||||
}
|
||||
|
||||
static char const *naps = "</span>";
|
||||
|
||||
report generate_report(TYPE type,
|
||||
const team &viewing_team, int current_side, int playing_side,
|
||||
const map_location& loc, const map_location& mouseover, const map_location& displayed_unit_hex,
|
||||
const std::set<std::string> &observers,
|
||||
const config& level, bool show_everything)
|
||||
{
|
||||
unit_map &units = *resources::units;
|
||||
gamemap &map = *resources::game_map;
|
||||
std::vector<team> &teams = *resources::teams;
|
||||
|
||||
const unit *u = NULL;
|
||||
|
||||
if((int(type) >= int(UNIT_REPORTS_BEGIN) && int(type) < int(UNIT_REPORTS_END)) || type == POSITION){
|
||||
u = get_visible_unit(displayed_unit_hex, viewing_team, show_everything);
|
||||
if (!u && type != POSITION) {
|
||||
return report();
|
||||
}
|
||||
}
|
||||
|
||||
std::ostringstream str;
|
||||
std::ostringstream tooltip;
|
||||
using utils::signed_percent;
|
||||
using font::span_color;
|
||||
|
||||
switch(type) {
|
||||
case UNIT_NAME:
|
||||
str << "<b>" << u->name() << "</b>";
|
||||
|
||||
tooltip << _("Name: ")
|
||||
<< "<b>" << u->name() << "</b>";
|
||||
|
||||
return report(str.str(), "", tooltip.str());
|
||||
case UNIT_TYPE: {
|
||||
str << span_color(font::unit_type_color) << u->type_name() << naps;
|
||||
|
||||
tooltip << _("Type: ")
|
||||
<< "<b>" << u->type_name() << "</b>\n"
|
||||
<< u->unit_description();
|
||||
|
||||
const std::string help_page = "unit_" + u->type_id();
|
||||
|
||||
return report(str.str(), "", tooltip.str(), help_page);
|
||||
}
|
||||
case UNIT_RACE: {
|
||||
str << span_color(font::race_color)
|
||||
<< u->race()->name(u->gender()) << naps;
|
||||
|
||||
tooltip << _("Race: ")
|
||||
<< "<b>" << u->race()->name(u->gender()) << "</b>";
|
||||
|
||||
const std::string help_page = "..race_" + u->race()->id();
|
||||
|
||||
return report(str.str(), "", tooltip.str(), help_page);
|
||||
}
|
||||
case UNIT_SIDE: {
|
||||
std::string flag_icon = teams[u->side() - 1].flag_icon();
|
||||
std::string old_rgb = game_config::flag_rgb;
|
||||
std::string new_rgb = team::get_side_color_index(u->side());
|
||||
std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";
|
||||
|
||||
if(flag_icon.empty()) {
|
||||
flag_icon = game_config::images::flag_icon;
|
||||
}
|
||||
|
||||
image::locator flag_icon_img(flag_icon, mods);
|
||||
return report("", flag_icon_img, teams[u->side() - 1].current_player());
|
||||
}
|
||||
case UNIT_LEVEL: {
|
||||
str << u->level();
|
||||
|
||||
tooltip << _("Level: ")
|
||||
<< "<b>" << u->level() << "</b>\n";
|
||||
|
||||
const std::vector<std::string>& adv_to = u->advances_to();
|
||||
if(adv_to.empty()) {
|
||||
tooltip << _("No advancement");
|
||||
} else {
|
||||
tooltip << _("Advances to:") << "\n"
|
||||
<< "<b>\t" << utils::join(adv_to, "\n\t") << "</b>";
|
||||
}
|
||||
|
||||
return report(str.str(), "", tooltip.str());
|
||||
}
|
||||
case UNIT_AMLA: {
|
||||
report res;
|
||||
typedef std::pair<std::string, std::string> pair_string;
|
||||
foreach(const pair_string& ps, u->amla_icons()) {
|
||||
res.add_image(ps.first,ps.second);
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
case UNIT_TRAITS: {
|
||||
report res;
|
||||
const std::vector<t_string>& traits = u->trait_names();
|
||||
const std::vector<t_string>& descriptions = u->trait_descriptions();
|
||||
unsigned int nb = traits.size();
|
||||
for(unsigned int i = 0; i < nb; ++i) {
|
||||
str << traits[i];
|
||||
if(i != nb - 1 )
|
||||
str << ", ";
|
||||
tooltip << _("Trait: ")
|
||||
<< "<b>" << traits[i] << "</b>\n"
|
||||
<< descriptions[i];
|
||||
|
||||
res.add_text(flush(str), flush(tooltip));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
case UNIT_STATUS: {
|
||||
report res;
|
||||
if (map.on_board(displayed_unit_hex) &&
|
||||
u->invisible(displayed_unit_hex))
|
||||
{
|
||||
add_status(res, "misc/invisible.png", N_("invisible: "),
|
||||
N_("This unit is invisible. It cannot be seen or attacked by enemy units."));
|
||||
}
|
||||
if (u->get_state(unit::STATE_SLOWED)) {
|
||||
add_status(res, "misc/slowed.png", N_("slowed: "),
|
||||
N_("This unit has been slowed. It will only deal half its normal damage when attacking and its movement cost is doubled."));
|
||||
}
|
||||
if (u->get_state(unit::STATE_POISONED)) {
|
||||
add_status(res, "misc/poisoned.png", N_("poisoned: "),
|
||||
N_("This unit is poisoned. It will lose 8 HP every turn until it can seek a cure to the poison in a village or from a friendly unit with the ‘cures’ ability.\n\nUnits cannot be killed by poison alone. The poison will not reduce it below 1 HP."));
|
||||
}
|
||||
if (u->get_state(unit::STATE_PETRIFIED)) {
|
||||
add_status(res, "misc/petrified.png", N_("petrified: "),
|
||||
N_("This unit has been petrified. It may not move or attack."));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
case UNIT_ALIGNMENT: {
|
||||
const std::string &align = unit_type::alignment_description(u->alignment(), u->gender());
|
||||
const std::string &align_id = unit_type::alignment_id(u->alignment());
|
||||
int cm = combat_modifier(displayed_unit_hex, u->alignment(), u->is_fearless());
|
||||
|
||||
str << align << " (" << signed_percent(cm) << ")";
|
||||
tooltip << _("Alignment: ")
|
||||
<< "<b>" << align << "</b>\n"
|
||||
<< string_table[align_id + "_description"];
|
||||
return report(str.str(), "", tooltip.str(), "time_of_day");
|
||||
}
|
||||
case UNIT_ABILITIES: {
|
||||
report res;
|
||||
const std::vector<std::string> &abilities = u->ability_tooltips();
|
||||
for(std::vector<std::string>::const_iterator i = abilities.begin(); i != abilities.end(); ++i) {
|
||||
const std::string& name = gettext(i->c_str());
|
||||
str << name;
|
||||
if(i+2 != abilities.end())
|
||||
str << ", ";
|
||||
++i;
|
||||
//FIXME pull out ability's name from description
|
||||
tooltip << _("Ability: ")
|
||||
<< *i;
|
||||
const std::string help_page = "ability_" + name;
|
||||
|
||||
res.add_text(flush(str), flush(tooltip), help_page);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
case UNIT_HP: {
|
||||
str << span_color(u->hp_color()) << u->hitpoints()
|
||||
<< '/' << u->max_hitpoints() << naps;
|
||||
|
||||
std::set<std::string> resistances_table;
|
||||
|
||||
utils::string_map resistances = u->get_base_resistances();
|
||||
|
||||
bool att_def_diff = false;
|
||||
for(utils::string_map::iterator resist = resistances.begin();
|
||||
resist != resistances.end(); ++resist) {
|
||||
std::ostringstream line;
|
||||
line << gettext(resist->first.c_str()) << ": ";
|
||||
|
||||
// Some units have different resistances when
|
||||
// attacking or defending.
|
||||
int res_att = 100 - u->resistance_against(resist->first, true, displayed_unit_hex);
|
||||
int res_def = 100 - u->resistance_against(resist->first, false, displayed_unit_hex);
|
||||
if (res_att == res_def) {
|
||||
line << signed_percent(res_def) << "\n";
|
||||
} else {
|
||||
line << signed_percent(res_att) << " / " << signed_percent(res_def) << "\n";
|
||||
att_def_diff = true;
|
||||
}
|
||||
resistances_table.insert(line.str());
|
||||
}
|
||||
|
||||
tooltip << _("Resistances: ");
|
||||
if (att_def_diff)
|
||||
tooltip << _("(Att / Def)");
|
||||
tooltip << "\n";
|
||||
|
||||
// the STL set will give alphabetical sorting
|
||||
for(std::set<std::string>::iterator line = resistances_table.begin();
|
||||
line != resistances_table.end(); ++line) {
|
||||
tooltip << (*line);
|
||||
}
|
||||
|
||||
return report(str.str(), "", tooltip.str());
|
||||
}
|
||||
case UNIT_XP: {
|
||||
str << span_color(u->xp_color()) << u->experience()
|
||||
<< '/' << u->max_experience() << naps;
|
||||
|
||||
tooltip << _("Experience Modifier: ") << (!level["experience_modifier"].empty() ? level["experience_modifier"].str() : "100") << '%';
|
||||
return report(str.str(), "", tooltip.str());
|
||||
}
|
||||
case UNIT_ADVANCEMENT_OPTIONS: {
|
||||
report res;
|
||||
typedef std::pair<std::string, std::string> pair_string;
|
||||
foreach(const pair_string& ps, u->advancement_icons()){
|
||||
res.add_image(ps.first,ps.second);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
case UNIT_DEFENSE: {
|
||||
const t_translation::t_terrain terrain = map[displayed_unit_hex];
|
||||
int def = 100 - u->defense_modifier(terrain);
|
||||
SDL_Color color = int_to_color(game_config::red_to_green(def));
|
||||
str << span_color(color) << def << "%</span>";
|
||||
|
||||
|
||||
tooltip << _("Terrain: ")
|
||||
<< "<b>" << map.get_terrain_info(terrain).description() << "</b>\n";
|
||||
|
||||
const t_translation::t_list& underlyings = map.underlying_def_terrain(terrain);
|
||||
std::vector<int> t_defs;
|
||||
bool revert = false;
|
||||
if(underlyings.size() != 1 || underlyings.front() != terrain) {
|
||||
foreach(const t_translation::t_terrain& t, underlyings) {
|
||||
if(t == t_translation::MINUS) {
|
||||
revert = true;
|
||||
} else if(t == t_translation::PLUS) {
|
||||
revert = false;
|
||||
} else {
|
||||
int t_def = 100 - u->defense_modifier(t);
|
||||
SDL_Color color = int_to_color(game_config::red_to_green(t_def));
|
||||
tooltip << "\t" << map.get_terrain_info(t).description() << ": "
|
||||
<< span_color(color) << t_def << "%</span> "
|
||||
<< (revert ? _("maximum^max.") : _("minimum^min.")) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tooltip << "<b>" << _("Defense: ")
|
||||
<< span_color(color) << def << "%</span></b>";
|
||||
|
||||
return report(str.str(), "", tooltip.str());
|
||||
}
|
||||
case UNIT_MOVES: {
|
||||
float movement_frac = 1.0;
|
||||
if (u->side() == playing_side) {
|
||||
movement_frac = static_cast<float>(u->movement_left()) / std::max(1.0f, static_cast<float>(u->total_movement()));
|
||||
if (movement_frac > 1.0)
|
||||
movement_frac = 1.0;
|
||||
}
|
||||
|
||||
int grey = 128 + static_cast<int>((255-128) * movement_frac);
|
||||
SDL_Color c = create_color(grey, grey, grey);
|
||||
str << span_color(c) << u->movement_left()
|
||||
<< '/' << u->total_movement() << naps;
|
||||
break;
|
||||
}
|
||||
case UNIT_WEAPONS: {
|
||||
report res;
|
||||
|
||||
foreach (const attack_type &at, u->attacks())
|
||||
{
|
||||
at.set_specials_context(displayed_unit_hex, map_location(), *u);
|
||||
|
||||
int base_damage = at.damage();
|
||||
|
||||
int damage_multiplier = 100;
|
||||
|
||||
// Time of day bonus.
|
||||
int tod_bonus = combat_modifier(displayed_unit_hex, u->alignment(), u->is_fearless());
|
||||
damage_multiplier += tod_bonus;
|
||||
|
||||
// Leadership bonus.
|
||||
int leader_bonus = 0;
|
||||
if (under_leadership(units, displayed_unit_hex, &leader_bonus).valid())
|
||||
damage_multiplier += leader_bonus;
|
||||
|
||||
// assume no specific resistance
|
||||
damage_multiplier *= 100;
|
||||
|
||||
bool slowed = u->get_state(unit::STATE_SLOWED);
|
||||
|
||||
int damage_divisor = slowed ? 20000 : 10000;
|
||||
int damage = round_damage(base_damage, damage_multiplier, damage_divisor);
|
||||
|
||||
int base_nattacks = at.num_attacks();
|
||||
int nattacks = base_nattacks;
|
||||
// Compute swarm attacks:
|
||||
unit_ability_list swarm = at.get_specials("swarm");
|
||||
if(!swarm.empty()) {
|
||||
int swarm_max_attacks = swarm.highest("swarm_attacks_max",nattacks).first;
|
||||
int swarm_min_attacks = swarm.highest("swarm_attacks_min").first;
|
||||
int hitp = u->hitpoints();
|
||||
int mhitp = u->max_hitpoints();
|
||||
|
||||
nattacks = swarm_min_attacks + (swarm_max_attacks - swarm_min_attacks) * hitp / mhitp;
|
||||
}
|
||||
|
||||
SDL_Color dmg_color = font::weapon_color;
|
||||
float dmg_bonus = static_cast<float>(damage)/base_damage;
|
||||
if(dmg_bonus > 1.0)
|
||||
dmg_color = font::good_dmg_color;
|
||||
else if(dmg_bonus < 1.0)
|
||||
dmg_color = font::bad_dmg_color;
|
||||
|
||||
str << span_color(dmg_color)
|
||||
<< damage
|
||||
<< "</span>"
|
||||
<< span_color(font::weapon_color)
|
||||
<< font::weapon_numbers_sep << nattacks
|
||||
<< ' ' << at.name()
|
||||
<< "</span>\n";
|
||||
|
||||
tooltip << _("Weapon: ") << "<b>" << at.name() << "</b>\n"
|
||||
<< _("Damage: ") << "<b>" << damage << "</b>\n";
|
||||
// Damage calculations details:
|
||||
if(tod_bonus || leader_bonus || slowed) {
|
||||
tooltip << "\t" << _("Base damage: ") << base_damage << "\n";
|
||||
if (tod_bonus) {
|
||||
tooltip << "\t" << _("Time of day: ")
|
||||
<< utils::signed_percent(tod_bonus) << "\n";
|
||||
}
|
||||
if (leader_bonus) {
|
||||
tooltip << "\t" << _("Leadership: ")
|
||||
<< utils::signed_percent(leader_bonus) << "\n";
|
||||
}
|
||||
if(slowed) {
|
||||
tooltip << "\t" << _("Slowed: ") << "/ 2" << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
tooltip << _("Attacks: ") << "<b>" << nattacks << "</b>\n";
|
||||
if(nattacks != base_nattacks){
|
||||
tooltip << "\t" << _("Base attacks: ") << base_nattacks << "\n";
|
||||
int hp_ratio = u->hitpoints() * 100 / u->max_hitpoints();
|
||||
tooltip << "\t" << _("Swarm: ") << "* "<< hp_ratio <<"%" << "\n";
|
||||
}
|
||||
|
||||
res.add_text(flush(str), flush(tooltip));
|
||||
|
||||
std::string range = gettext(at.range().c_str());
|
||||
std::string lang_type = gettext(at.type().c_str());
|
||||
|
||||
str << span_color(font::weapon_details_color) << " "
|
||||
<< range << font::weapon_details_sep
|
||||
<< lang_type << "</span>\n";
|
||||
|
||||
tooltip << _("Weapon range: ") << "<b>" << range << "</b>\n"
|
||||
<< _("Damage type: ") << "<b>" << lang_type << "</b>\n"
|
||||
<< _("Damage versus: ") << "\n";
|
||||
|
||||
// Show this weapon damage and resistanceagainst all the different units.
|
||||
|
||||
// map storing each resistance value and types having it
|
||||
// we want weak resistances (=good damage) first
|
||||
std::map<int, std::set<std::string>, std::greater<int> > resistances;
|
||||
std::set<std::string> seen_types;
|
||||
const team& unit_team = teams[u->side() - 1];
|
||||
foreach(const unit& enemy, units) {
|
||||
// Don't show allies
|
||||
if (!unit_team.is_enemy(enemy.side()))
|
||||
continue;
|
||||
|
||||
// Don't show invisible units
|
||||
const map_location& loc = enemy.get_location();
|
||||
if (viewing_team.fogged(loc) || (viewing_team.is_enemy(enemy.side()) && enemy.invisible(loc)))
|
||||
continue;
|
||||
|
||||
bool new_type = seen_types.insert(enemy.type_id()).second;
|
||||
if(new_type) {
|
||||
int resistance = enemy.resistance_against(at, false, loc);
|
||||
resistances[resistance].insert(enemy.type_name());
|
||||
}
|
||||
}
|
||||
|
||||
// reset damage_multiplier
|
||||
damage_multiplier = 100;
|
||||
|
||||
// reset ToD bonus to a dummy location (to get global ToD)
|
||||
tod_bonus = combat_modifier(map_location::null_location, u->alignment(), u->is_fearless());
|
||||
damage_multiplier += tod_bonus;
|
||||
|
||||
//ignore leadership bonus
|
||||
|
||||
typedef std::pair<int, std::set<std::string> > resist_units;
|
||||
foreach(const resist_units& resist, resistances) {
|
||||
int damage = round_damage(base_damage, damage_multiplier * resist.first, damage_divisor);
|
||||
tooltip << "<b>" << damage << "</b> "
|
||||
<< "<i>(" << signed_percent(resist.first-100) << ")</i> : "
|
||||
<< utils::join(resist.second, ", ") << "\n";
|
||||
}
|
||||
|
||||
res.add_text(flush(str), flush(tooltip));
|
||||
|
||||
const std::string& accuracy_parry = at.accuracy_parry_description();
|
||||
if(!accuracy_parry.empty()){
|
||||
str << span_color(font::weapon_details_color)
|
||||
<< " " << accuracy_parry << "</span>\n";
|
||||
int accuracy = at.accuracy();
|
||||
if(accuracy) {
|
||||
tooltip << _("Accuracy:") << "<b>"
|
||||
<< signed_percent(accuracy) << "</b>\n";
|
||||
}
|
||||
int parry = at.parry();
|
||||
if(parry) {
|
||||
tooltip << _("Parry:") << "<b>"
|
||||
<< signed_percent(parry) << "</b>\n";
|
||||
}
|
||||
res.add_text(flush(str), flush(tooltip));
|
||||
}
|
||||
|
||||
const std::vector<t_string> &specials = at.special_tooltips();
|
||||
|
||||
if(! specials.empty()) {
|
||||
for(std::vector<t_string>::const_iterator sp_it = specials.begin(); sp_it != specials.end(); ++sp_it) {
|
||||
str << span_color(font::weapon_details_color)
|
||||
<< " " << *sp_it << "</span>\n";
|
||||
const std::string help_page = "weaponspecial_" + sp_it->base_str();
|
||||
++sp_it;
|
||||
//FIXME pull out special's name from description
|
||||
tooltip << _("Weapon special: ")
|
||||
<< *sp_it << '\n';
|
||||
|
||||
res.add_text(flush(str), flush(tooltip), help_page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
case UNIT_IMAGE:
|
||||
{
|
||||
// const std::vector<Uint32>& old_rgb = u->second.team_rgb_range();
|
||||
// color_range new_rgb = team::get_side_color_range(u->second.side());
|
||||
return report("", image::locator(u->absolute_image(), u->image_mods()), "");
|
||||
}
|
||||
case UNIT_PROFILE:
|
||||
return report("", u->small_profile(), "");
|
||||
case TIME_OF_DAY: {
|
||||
time_of_day tod;
|
||||
|
||||
if (viewing_team.shrouded(mouseover)) {
|
||||
// Don't show time on shrouded tiles.
|
||||
tod = resources::tod_manager->get_time_of_day();
|
||||
} else if (viewing_team.fogged(mouseover)) {
|
||||
// Don't show illuminated time on fogged tiles.
|
||||
tod = resources::tod_manager->get_time_of_day(mouseover);
|
||||
} else {
|
||||
tod = resources::tod_manager->time_of_day_at(mouseover);
|
||||
}
|
||||
|
||||
int b = tod.lawful_bonus;
|
||||
int c = tod.liminal_bonus;
|
||||
tooltip << tod.name << '\n'
|
||||
<< _("Lawful units: ") << signed_percent(b) << "\n"
|
||||
<< _("Neutral units: ") << signed_percent(0) << "\n"
|
||||
<< _("Chaotic units: ") << signed_percent(-b);
|
||||
|
||||
if (tod.liminal_present)
|
||||
tooltip << "\n" << _("Liminal units: ") << signed_percent(c);
|
||||
|
||||
std::string tod_image = tod.image;
|
||||
if (tod.lawful_bonus_modified > 0) tod_image += "~BRIGHTEN()";
|
||||
else if (tod.lawful_bonus_modified < 0) tod_image += "~DARKEN()";
|
||||
if (preferences::flip_time()) tod_image += "~FL(horiz)";
|
||||
|
||||
return report("",tod_image,tooltip.str(),"time_of_day");
|
||||
}
|
||||
case TURN: {
|
||||
str << resources::tod_manager->turn();
|
||||
int nb = resources::tod_manager->number_of_turns();
|
||||
if (nb != -1) str << '/' << nb;
|
||||
break;
|
||||
}
|
||||
// For the following status reports, show them in gray text
|
||||
// when it is not the active player's turn.
|
||||
case GOLD: {
|
||||
//Supposes the full/"pathfind" unit map is applied
|
||||
int fake_gold = viewing_team.gold() - resources::whiteboard->get_spent_gold_for(current_side);
|
||||
char const *end = naps;
|
||||
if (current_side != playing_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
else if (fake_gold < 0)
|
||||
str << span_color(font::BAD_COLOR);
|
||||
else
|
||||
end = "";
|
||||
str << fake_gold << end;
|
||||
break;
|
||||
}
|
||||
case VILLAGES: {
|
||||
const team_data data = calculate_team_data(viewing_team,current_side);
|
||||
if (current_side != playing_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
str << data.villages << '/';
|
||||
if (viewing_team.uses_shroud()) {
|
||||
int unshrouded_villages = 0;
|
||||
std::vector<map_location>::const_iterator i = map.villages().begin();
|
||||
for (; i != map.villages().end(); ++i) {
|
||||
if (!viewing_team.shrouded(*i))
|
||||
++unshrouded_villages;
|
||||
}
|
||||
str << unshrouded_villages;
|
||||
} else {
|
||||
str << map.villages().size();
|
||||
}
|
||||
if (current_side != playing_side)
|
||||
str << naps;
|
||||
break;
|
||||
}
|
||||
case NUM_UNITS: {
|
||||
if (current_side != playing_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
str << side_units(current_side);
|
||||
if (current_side != playing_side)
|
||||
str << naps;
|
||||
break;
|
||||
}
|
||||
case UPKEEP: {
|
||||
const team_data data = calculate_team_data(viewing_team,current_side);
|
||||
if (current_side != playing_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
str << data.expenses << " (" << data.upkeep << ")";
|
||||
if (current_side != playing_side)
|
||||
str << naps;
|
||||
break;
|
||||
}
|
||||
case EXPENSES: {
|
||||
const team_data data = calculate_team_data(viewing_team,current_side);
|
||||
if (current_side != playing_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
str << data.expenses;
|
||||
if (current_side != playing_side)
|
||||
str << naps;
|
||||
break;
|
||||
}
|
||||
case INCOME: {
|
||||
team_data data = calculate_team_data(viewing_team, current_side);
|
||||
char const *end = naps;
|
||||
if (current_side != playing_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
else if (data.net_income < 0)
|
||||
str << span_color(font::BAD_COLOR);
|
||||
else
|
||||
end = "";
|
||||
str << data.net_income << end;
|
||||
break;
|
||||
}
|
||||
case TERRAIN: {
|
||||
if(!map.on_board(mouseover) || viewing_team.shrouded(mouseover))
|
||||
break;
|
||||
|
||||
const t_translation::t_terrain terrain = map.get_terrain(mouseover);
|
||||
if (terrain == t_translation::OFF_MAP_USER)
|
||||
break;
|
||||
|
||||
const t_translation::t_list& underlying = map.underlying_union_terrain(terrain);
|
||||
|
||||
if(map.is_village(mouseover)) {
|
||||
int owner = village_owner(mouseover, teams) + 1;
|
||||
if(owner == 0 || viewing_team.fogged(mouseover)) {
|
||||
str << map.get_terrain_info(terrain).income_description();
|
||||
} else if(owner == current_side) {
|
||||
str << map.get_terrain_info(terrain).income_description_own();
|
||||
} else if(viewing_team.is_enemy(owner)) {
|
||||
str << map.get_terrain_info(terrain).income_description_enemy();
|
||||
} else {
|
||||
str << map.get_terrain_info(terrain).income_description_ally();
|
||||
}
|
||||
str << " ";
|
||||
} else {
|
||||
str << map.get_terrain_info(terrain).description();
|
||||
}
|
||||
|
||||
if(underlying.size() != 1 || underlying.front() != terrain) {
|
||||
str << " (";
|
||||
|
||||
for(t_translation::t_list::const_iterator i =
|
||||
underlying.begin(); i != underlying.end(); ++i) {
|
||||
|
||||
str << map.get_terrain_info(*i).name();
|
||||
if(i+1 != underlying.end()) {
|
||||
str << ",";
|
||||
}
|
||||
}
|
||||
str << ")";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case POSITION: {
|
||||
if(!map.on_board(mouseover)) {
|
||||
break;
|
||||
}
|
||||
|
||||
const t_translation::t_terrain terrain = map[mouseover];
|
||||
|
||||
if (terrain == t_translation::OFF_MAP_USER)
|
||||
break;
|
||||
|
||||
str << mouseover;
|
||||
|
||||
if (!u)
|
||||
break;
|
||||
if(displayed_unit_hex != mouseover && displayed_unit_hex != loc)
|
||||
break;
|
||||
if(viewing_team.shrouded(mouseover))
|
||||
break;
|
||||
|
||||
int move_cost = u->movement_cost(terrain);
|
||||
int defense = 100 - u->defense_modifier(terrain);
|
||||
|
||||
if(move_cost < unit_movement_type::UNREACHABLE) {
|
||||
str << " (" << defense << "%," << move_cost << ")";
|
||||
} else if (mouseover == displayed_unit_hex) {
|
||||
str << " (" << defense << "%,-)";
|
||||
} else {
|
||||
str << " (-)";
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SIDE_PLAYING: {
|
||||
std::string flag_icon = teams[playing_side-1].flag_icon();
|
||||
std::string old_rgb = game_config::flag_rgb;
|
||||
std::string new_rgb = team::get_side_color_index(playing_side);
|
||||
std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";
|
||||
|
||||
if(flag_icon.empty()) {
|
||||
flag_icon = game_config::images::flag_icon;
|
||||
}
|
||||
|
||||
image::locator flag_icon_img(flag_icon, mods);
|
||||
return report("",flag_icon_img,teams[playing_side-1].current_player());
|
||||
}
|
||||
|
||||
case OBSERVERS: {
|
||||
if(observers.empty()) {
|
||||
return report();
|
||||
}
|
||||
|
||||
str << _("Observers:") << "\n";
|
||||
|
||||
for(std::set<std::string>::const_iterator i = observers.begin(); i != observers.end(); ++i) {
|
||||
str << *i << "\n";
|
||||
}
|
||||
|
||||
return report("",game_config::images::observer,str.str());
|
||||
}
|
||||
#ifdef DISABLE_EDITOR
|
||||
case EDITOR_SELECTED_TERRAIN:
|
||||
case EDITOR_LEFT_BUTTON_FUNCTION:
|
||||
return report();
|
||||
#else
|
||||
case EDITOR_SELECTED_TERRAIN: {
|
||||
if (editor::selected_terrain.empty())
|
||||
return report();
|
||||
else
|
||||
return report(editor::selected_terrain);
|
||||
}
|
||||
case EDITOR_LEFT_BUTTON_FUNCTION: {
|
||||
if (editor::left_button_function.empty())
|
||||
return report();
|
||||
else
|
||||
return report(editor::left_button_function);
|
||||
}
|
||||
#endif
|
||||
case REPORT_COUNTDOWN: {
|
||||
int min;
|
||||
int sec;
|
||||
if (viewing_team.countdown_time() > 0){
|
||||
sec = viewing_team.countdown_time() / 1000;
|
||||
char const *end = naps;
|
||||
if (current_side != playing_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
else if (sec < 60)
|
||||
str << "<span foreground=\"#c80000\">";
|
||||
else if (sec < 120)
|
||||
str << "<span foreground=\"#c8c800\">";
|
||||
else
|
||||
end = "";
|
||||
|
||||
min = sec / 60;
|
||||
str << min << ":";
|
||||
sec = sec % 60;
|
||||
if (sec < 10) {
|
||||
str << "0";
|
||||
}
|
||||
str << sec << end;
|
||||
break;
|
||||
} // Intentional fall-through to REPORT_CLOCK
|
||||
// if the time countdown isn't valid.
|
||||
// If there is no turn time limit,
|
||||
// then we display the clock instead.
|
||||
}
|
||||
case REPORT_CLOCK: {
|
||||
time_t t = std::time(NULL);
|
||||
struct tm *lt = std::localtime(&t);
|
||||
if (lt) {
|
||||
char temp[10];
|
||||
size_t s = std::strftime(temp, 10, preferences::clock_format().c_str(), lt);
|
||||
if(s>0) {
|
||||
return report(temp);
|
||||
} else {
|
||||
return report();
|
||||
}
|
||||
} else {
|
||||
return report();
|
||||
}
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
return report(str.str());
|
||||
}
|
||||
|
||||
} // end namespace reports
|
||||
|
855
src/reports.cpp
855
src/reports.cpp
|
@ -15,9 +15,23 @@
|
|||
|
||||
#include "global.hpp"
|
||||
|
||||
#include "actions.hpp"
|
||||
#include "font.hpp"
|
||||
#include "foreach.hpp"
|
||||
#include "game_preferences.hpp"
|
||||
#include "gettext.hpp"
|
||||
#include "language.hpp"
|
||||
#include "map.hpp"
|
||||
#include "marked-up_text.hpp"
|
||||
#include "reports.hpp"
|
||||
#include "resources.hpp"
|
||||
#include "team.hpp"
|
||||
#include "tod_manager.hpp"
|
||||
#include "unit.hpp"
|
||||
#include "whiteboard/manager.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <ctime>
|
||||
|
||||
namespace {
|
||||
const std::string report_names[] = {
|
||||
|
@ -54,3 +68,844 @@ void report::add_image(const std::string& image, const std::string& tooltip,
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
using reports::report;
|
||||
using reports::report_data;
|
||||
|
||||
using font::span_color;
|
||||
|
||||
static void add_status(report &r,
|
||||
char const *path, char const *desc1, char const *desc2)
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << gettext(desc1) << gettext(desc2);
|
||||
r.add_image(path, s.str());
|
||||
}
|
||||
|
||||
static std::string flush(std::ostringstream &s)
|
||||
{
|
||||
std::string r(s.str());
|
||||
s.str(std::string());
|
||||
return r;
|
||||
}
|
||||
|
||||
static char const *naps = "</span>";
|
||||
|
||||
static unit *get_visible_unit(const report_data &data)
|
||||
{
|
||||
return get_visible_unit(data.displayed_unit_hex,
|
||||
(*resources::teams)[data.viewing_side - 1], data.show_everything);
|
||||
}
|
||||
|
||||
static report gray_inactive(const report_data &data, const std::string &str)
|
||||
{
|
||||
if (data.current_side == data.active_side)
|
||||
return report(str);
|
||||
return report(span_color(font::GRAY_COLOR) + str + naps);
|
||||
}
|
||||
|
||||
static report report_unit_name(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str, tooltip;
|
||||
str << "<b>" << u->name() << "</b>";
|
||||
tooltip << _("Name: ") << "<b>" << u->name() << "</b>";
|
||||
return report(str.str(), "", tooltip.str());
|
||||
}
|
||||
|
||||
static report report_unit_type(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str, tooltip;
|
||||
str << span_color(font::unit_type_color) << u->type_name() << naps;
|
||||
tooltip << _("Type: ") << "<b>" << u->type_name() << "</b>\n"
|
||||
<< u->unit_description();
|
||||
return report(str.str(), "", tooltip.str(), "unit_" + u->type_id());
|
||||
}
|
||||
|
||||
static report report_unit_race(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str, tooltip;
|
||||
str << span_color(font::race_color) << u->race()->name(u->gender()) << naps;
|
||||
tooltip << _("Race: ") << "<b>" << u->race()->name(u->gender()) << "</b>";
|
||||
return report(str.str(), "", tooltip.str(), "..race_" + u->race()->id());
|
||||
}
|
||||
|
||||
static report report_unit_side(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
const team &u_team = (*resources::teams)[u->side() - 1];
|
||||
std::string flag_icon = u_team.flag_icon();
|
||||
std::string old_rgb = game_config::flag_rgb;
|
||||
std::string new_rgb = team::get_side_color_index(u->side());
|
||||
std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";
|
||||
if (flag_icon.empty())
|
||||
flag_icon = game_config::images::flag_icon;
|
||||
image::locator flag_icon_img(flag_icon, mods);
|
||||
return report("", flag_icon_img, u_team.current_player());
|
||||
}
|
||||
|
||||
static report report_unit_level(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str, tooltip;
|
||||
str << u->level();
|
||||
tooltip << _("Level: ") << "<b>" << u->level() << "</b>\n";
|
||||
const std::vector<std::string> &adv_to = u->advances_to();
|
||||
if (adv_to.empty())
|
||||
tooltip << _("No advancement");
|
||||
else
|
||||
tooltip << _("Advances to:") << "\n<b>\t"
|
||||
<< utils::join(adv_to, "\n\t") << "</b>";
|
||||
return report(str.str(), "", tooltip.str());
|
||||
}
|
||||
|
||||
static report report_unit_amla(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
report res;
|
||||
typedef std::pair<std::string, std::string> pair_string;
|
||||
foreach(const pair_string &ps, u->amla_icons()) {
|
||||
res.add_image(ps.first,ps.second);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static report report_unit_traits(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
report res;
|
||||
const std::vector<t_string> &traits = u->trait_names();
|
||||
const std::vector<t_string> &descriptions = u->trait_descriptions();
|
||||
unsigned nb = traits.size();
|
||||
for (unsigned i = 0; i < nb; ++i)
|
||||
{
|
||||
std::ostringstream str, tooltip;
|
||||
str << traits[i];
|
||||
if (i != nb - 1 ) str << ", ";
|
||||
tooltip << _("Trait: ") << "<b>" << traits[i] << "</b>\n"
|
||||
<< descriptions[i];
|
||||
res.add_text(str.str(), tooltip.str());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static report report_unit_status(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
report res;
|
||||
if (resources::game_map->on_board(data.displayed_unit_hex) &&
|
||||
u->invisible(data.displayed_unit_hex))
|
||||
{
|
||||
add_status(res, "misc/invisible.png", N_("invisible: "),
|
||||
N_("This unit is invisible. It cannot be seen or attacked by enemy units."));
|
||||
}
|
||||
if (u->get_state(unit::STATE_SLOWED)) {
|
||||
add_status(res, "misc/slowed.png", N_("slowed: "),
|
||||
N_("This unit has been slowed. It will only deal half its normal damage when attacking and its movement cost is doubled."));
|
||||
}
|
||||
if (u->get_state(unit::STATE_POISONED)) {
|
||||
add_status(res, "misc/poisoned.png", N_("poisoned: "),
|
||||
N_("This unit is poisoned. It will lose 8 HP every turn until it can seek a cure to the poison in a village or from a friendly unit with the ‘cures’ ability.\n\nUnits cannot be killed by poison alone. The poison will not reduce it below 1 HP."));
|
||||
}
|
||||
if (u->get_state(unit::STATE_PETRIFIED)) {
|
||||
add_status(res, "misc/petrified.png", N_("petrified: "),
|
||||
N_("This unit has been petrified. It may not move or attack."));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static report report_unit_alignment(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str, tooltip;
|
||||
char const *align = unit_type::alignment_description(u->alignment(), u->gender());
|
||||
std::string align_id = unit_type::alignment_id(u->alignment());
|
||||
int cm = combat_modifier(data.displayed_unit_hex, u->alignment(), u->is_fearless());
|
||||
str << align << " (" << utils::signed_percent(cm) << ")";
|
||||
tooltip << _("Alignment: ") << "<b>" << align << "</b>\n"
|
||||
<< string_table[align_id + "_description"];
|
||||
return report(str.str(), "", tooltip.str(), "time_of_day");
|
||||
}
|
||||
|
||||
static report report_unit_abilities(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
report res;
|
||||
const std::vector<std::string> &abilities = u->ability_tooltips();
|
||||
for (std::vector<std::string>::const_iterator i = abilities.begin(),
|
||||
i_end = abilities.end(); i != i_end; ++i)
|
||||
{
|
||||
std::ostringstream str, tooltip;
|
||||
const std::string &name = *i;
|
||||
str << gettext(name.c_str());
|
||||
if (i + 2 != i_end) str << ", ";
|
||||
++i;
|
||||
tooltip << _("Ability: ") << *i;
|
||||
res.add_text(str.str(), tooltip.str(), "ability_" + name);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static report report_unit_hp(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str, tooltip;
|
||||
str << span_color(u->hp_color()) << u->hitpoints()
|
||||
<< '/' << u->max_hitpoints() << naps;
|
||||
|
||||
std::set<std::string> resistances_table;
|
||||
utils::string_map resistances = u->get_base_resistances();
|
||||
|
||||
bool att_def_diff = false;
|
||||
foreach (const utils::string_map::value_type &resist, u->get_base_resistances())
|
||||
{
|
||||
std::ostringstream line;
|
||||
line << gettext(resist.first.c_str()) << ": ";
|
||||
// Some units have different resistances when attacking or defending.
|
||||
int res_att = 100 - u->resistance_against(resist.first, true, data.displayed_unit_hex);
|
||||
int res_def = 100 - u->resistance_against(resist.first, false, data.displayed_unit_hex);
|
||||
if (res_att == res_def) {
|
||||
line << utils::signed_percent(res_def) << "\n";
|
||||
} else {
|
||||
line << utils::signed_percent(res_att) << " / " << utils::signed_percent(res_def) << '\n';
|
||||
att_def_diff = true;
|
||||
}
|
||||
resistances_table.insert(line.str());
|
||||
}
|
||||
|
||||
tooltip << _("Resistances: ");
|
||||
if (att_def_diff)
|
||||
tooltip << _("(Att / Def)");
|
||||
tooltip << '\n';
|
||||
foreach (const std::string &line, resistances_table) {
|
||||
tooltip << line;
|
||||
}
|
||||
return report(str.str(), "", tooltip.str());
|
||||
}
|
||||
|
||||
static report report_unit_xp(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str, tooltip;
|
||||
str << span_color(u->xp_color()) << u->experience()
|
||||
<< '/' << u->max_experience() << naps;
|
||||
|
||||
std::string exp_mod = data.level["experience_modifier"].str();
|
||||
tooltip << _("Experience Modifier: ") << (!exp_mod.empty() ? exp_mod : "100") << '%';
|
||||
return report(str.str(), "", tooltip.str());
|
||||
}
|
||||
|
||||
static report report_unit_advancement_options(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
report res;
|
||||
typedef std::pair<std::string, std::string> pair_string;
|
||||
foreach (const pair_string &ps, u->advancement_icons()) {
|
||||
res.add_image(ps.first,ps.second);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static report report_unit_defense(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str, tooltip;
|
||||
const gamemap &map = *resources::game_map;
|
||||
const t_translation::t_terrain &terrain = map[data.displayed_unit_hex];
|
||||
int def = 100 - u->defense_modifier(terrain);
|
||||
SDL_Color color = int_to_color(game_config::red_to_green(def));
|
||||
str << span_color(color) << def << "%</span>";
|
||||
tooltip << _("Terrain: ") << "<b>" << map.get_terrain_info(terrain).description() << "</b>\n";
|
||||
|
||||
const t_translation::t_list &underlyings = map.underlying_def_terrain(terrain);
|
||||
std::vector<int> t_defs;
|
||||
bool revert = false;
|
||||
if (underlyings.size() != 1 || underlyings.front() != terrain)
|
||||
{
|
||||
foreach (const t_translation::t_terrain &t, underlyings)
|
||||
{
|
||||
if (t == t_translation::MINUS) {
|
||||
revert = true;
|
||||
} else if (t == t_translation::PLUS) {
|
||||
revert = false;
|
||||
} else {
|
||||
int t_def = 100 - u->defense_modifier(t);
|
||||
SDL_Color color = int_to_color(game_config::red_to_green(t_def));
|
||||
tooltip << '\t' << map.get_terrain_info(t).description() << ": "
|
||||
<< span_color(color) << t_def << "%</span> "
|
||||
<< (revert ? _("maximum^max.") : _("minimum^min.")) << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tooltip << "<b>" << _("Defense: ") << span_color(color) << def << "%</span></b>";
|
||||
return report(str.str(), "", tooltip.str());
|
||||
}
|
||||
|
||||
static report report_unit_moves(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str;
|
||||
double movement_frac = 1.0;
|
||||
if (u->side() == data.active_side) {
|
||||
movement_frac = double(u->movement_left()) / std::max<int>(1, u->total_movement());
|
||||
if (movement_frac > 1.0)
|
||||
movement_frac = 1.0;
|
||||
}
|
||||
|
||||
int grey = 128 + int((255 - 128) * movement_frac);
|
||||
SDL_Color c = create_color(grey, grey, grey);
|
||||
str << span_color(c) << u->movement_left() << '/' << u->total_movement() << naps;
|
||||
return report(str.str());
|
||||
}
|
||||
|
||||
static report report_unit_weapons(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
std::ostringstream str, tooltip;
|
||||
report res;
|
||||
|
||||
foreach (const attack_type &at, u->attacks())
|
||||
{
|
||||
at.set_specials_context(data.displayed_unit_hex, map_location(), *u);
|
||||
int base_damage = at.damage();
|
||||
int damage_multiplier = 100;
|
||||
int tod_bonus = combat_modifier(data.displayed_unit_hex, u->alignment(), u->is_fearless());
|
||||
damage_multiplier += tod_bonus;
|
||||
int leader_bonus = 0;
|
||||
if (under_leadership(*resources::units, data.displayed_unit_hex, &leader_bonus).valid())
|
||||
damage_multiplier += leader_bonus;
|
||||
|
||||
// Assume no specific resistance.
|
||||
damage_multiplier *= 100;
|
||||
bool slowed = u->get_state(unit::STATE_SLOWED);
|
||||
int damage_divisor = slowed ? 20000 : 10000;
|
||||
int damage = round_damage(base_damage, damage_multiplier, damage_divisor);
|
||||
|
||||
int base_nattacks = at.num_attacks();
|
||||
int nattacks = base_nattacks;
|
||||
unit_ability_list swarm = at.get_specials("swarm");
|
||||
if (!swarm.empty())
|
||||
{
|
||||
int swarm_max_attacks = swarm.highest("swarm_attacks_max", nattacks).first;
|
||||
int swarm_min_attacks = swarm.highest("swarm_attacks_min").first;
|
||||
int hitp = u->hitpoints();
|
||||
int mhitp = u->max_hitpoints();
|
||||
nattacks = swarm_min_attacks + (swarm_max_attacks - swarm_min_attacks) * hitp / mhitp;
|
||||
}
|
||||
|
||||
SDL_Color dmg_color = font::weapon_color;
|
||||
double dmg_bonus = double(damage) / base_damage;
|
||||
if (dmg_bonus > 1.0)
|
||||
dmg_color = font::good_dmg_color;
|
||||
else if (dmg_bonus < 1.0)
|
||||
dmg_color = font::bad_dmg_color;
|
||||
|
||||
str << span_color(dmg_color) << damage << naps << span_color(font::weapon_color)
|
||||
<< font::weapon_numbers_sep << nattacks << ' ' << at.name()
|
||||
<< "</span>\n";
|
||||
tooltip << _("Weapon: ") << "<b>" << at.name() << "</b>\n"
|
||||
<< _("Damage: ") << "<b>" << damage << "</b>\n";
|
||||
|
||||
if (tod_bonus || leader_bonus || slowed)
|
||||
{
|
||||
tooltip << '\t' << _("Base damage: ") << base_damage << '\n';
|
||||
if (tod_bonus) {
|
||||
tooltip << '\t' << _("Time of day: ")
|
||||
<< utils::signed_percent(tod_bonus) << '\n';
|
||||
}
|
||||
if (leader_bonus) {
|
||||
tooltip << '\t' << _("Leadership: ")
|
||||
<< utils::signed_percent(leader_bonus) << '\n';
|
||||
}
|
||||
if (slowed) {
|
||||
tooltip << '\t' << _("Slowed: ") << "/ 2" << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
tooltip << _("Attacks: ") << "<b>" << nattacks << "</b>\n";
|
||||
if (nattacks != base_nattacks){
|
||||
tooltip << '\t' << _("Base attacks: ") << base_nattacks << '\n';
|
||||
int hp_ratio = u->hitpoints() * 100 / u->max_hitpoints();
|
||||
tooltip << '\t' << _("Swarm: ") << "* "<< hp_ratio << "%\n";
|
||||
}
|
||||
|
||||
res.add_text(flush(str), flush(tooltip));
|
||||
|
||||
std::string range = gettext(at.range().c_str());
|
||||
std::string lang_type = gettext(at.type().c_str());
|
||||
|
||||
str << span_color(font::weapon_details_color) << " "
|
||||
<< range << font::weapon_details_sep
|
||||
<< lang_type << "</span>\n";
|
||||
|
||||
tooltip << _("Weapon range: ") << "<b>" << range << "</b>\n"
|
||||
<< _("Damage type: ") << "<b>" << lang_type << "</b>\n"
|
||||
<< _("Damage versus: ") << '\n';
|
||||
|
||||
// Show this weapon damage and resistance against all the different units.
|
||||
// We want weak resistances (= good damage) first.
|
||||
std::map<int, std::set<std::string>, std::greater<int> > resistances;
|
||||
std::set<std::string> seen_types;
|
||||
const team &unit_team = (*resources::teams)[u->side() - 1];
|
||||
const team &viewing_team = (*resources::teams)[data.viewing_side - 1];
|
||||
foreach(const unit &enemy, *resources::units)
|
||||
{
|
||||
if (!unit_team.is_enemy(enemy.side()))
|
||||
continue;
|
||||
const map_location &loc = enemy.get_location();
|
||||
if (viewing_team.fogged(loc) ||
|
||||
(viewing_team.is_enemy(enemy.side()) && enemy.invisible(loc)))
|
||||
continue;
|
||||
bool new_type = seen_types.insert(enemy.type_id()).second;
|
||||
if (new_type) {
|
||||
int resistance = enemy.resistance_against(at, false, loc);
|
||||
resistances[resistance].insert(enemy.type_name());
|
||||
}
|
||||
}
|
||||
|
||||
// Get global ToD.
|
||||
damage_multiplier = 100;
|
||||
tod_bonus = combat_modifier(map_location::null_location, u->alignment(), u->is_fearless());
|
||||
damage_multiplier += tod_bonus;
|
||||
|
||||
typedef std::pair<int, std::set<std::string> > resist_units;
|
||||
foreach (const resist_units &resist, resistances) {
|
||||
int damage = round_damage(base_damage, damage_multiplier * resist.first, damage_divisor);
|
||||
tooltip << "<b>" << damage << "</b> "
|
||||
<< "<i>(" << utils::signed_percent(resist.first-100) << ")</i> : "
|
||||
<< utils::join(resist.second, ", ") << '\n';
|
||||
}
|
||||
res.add_text(flush(str), flush(tooltip));
|
||||
|
||||
const std::string &accuracy_parry = at.accuracy_parry_description();
|
||||
if (!accuracy_parry.empty())
|
||||
{
|
||||
str << span_color(font::weapon_details_color)
|
||||
<< " " << accuracy_parry << "</span>\n";
|
||||
int accuracy = at.accuracy();
|
||||
if (accuracy) {
|
||||
tooltip << _("Accuracy:") << "<b>"
|
||||
<< utils::signed_percent(accuracy) << "</b>\n";
|
||||
}
|
||||
int parry = at.parry();
|
||||
if (parry) {
|
||||
tooltip << _("Parry:") << "<b>"
|
||||
<< utils::signed_percent(parry) << "</b>\n";
|
||||
}
|
||||
res.add_text(flush(str), flush(tooltip));
|
||||
}
|
||||
|
||||
const std::vector<t_string> &specials = at.special_tooltips();
|
||||
if (!specials.empty())
|
||||
{
|
||||
for (std::vector<t_string>::const_iterator sp_it = specials.begin(),
|
||||
sp_end = specials.end(); sp_it != sp_end; ++sp_it)
|
||||
{
|
||||
str << span_color(font::weapon_details_color)
|
||||
<< " " << *sp_it << "</span>\n";
|
||||
std::string help_page = "weaponspecial_" + sp_it->base_str();
|
||||
++sp_it;
|
||||
//FIXME pull out special's name from description
|
||||
tooltip << _("Weapon special: ") << *sp_it << '\n';
|
||||
res.add_text(flush(str), flush(tooltip), help_page);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static report report_unit_image(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
return report("", image::locator(u->absolute_image(), u->image_mods()), "");
|
||||
}
|
||||
|
||||
static report report_unit_profile(const report_data &data)
|
||||
{
|
||||
unit *u = get_visible_unit(data);
|
||||
if (!u) return report();
|
||||
return report("", u->small_profile(), "");
|
||||
}
|
||||
|
||||
static report report_time_of_day(const report_data &data)
|
||||
{
|
||||
std::ostringstream tooltip;
|
||||
time_of_day tod;
|
||||
const team &viewing_team = (*resources::teams)[data.viewing_side - 1];
|
||||
if (viewing_team.shrouded(data.mouseover_hex)) {
|
||||
// Don't show time on shrouded tiles.
|
||||
tod = resources::tod_manager->get_time_of_day();
|
||||
} else if (viewing_team.fogged(data.mouseover_hex)) {
|
||||
// Don't show illuminated time on fogged tiles.
|
||||
tod = resources::tod_manager->get_time_of_day(data.mouseover_hex);
|
||||
} else {
|
||||
tod = resources::tod_manager->time_of_day_at(data.mouseover_hex);
|
||||
}
|
||||
|
||||
int b = tod.lawful_bonus;
|
||||
int c = tod.liminal_bonus;
|
||||
tooltip << tod.name << '\n'
|
||||
<< _("Lawful units: ") << utils::signed_percent(b) << '\n'
|
||||
<< _("Neutral units: ") << utils::signed_percent(0) << '\n'
|
||||
<< _("Chaotic units: ") << utils::signed_percent(-b);
|
||||
if (tod.liminal_present)
|
||||
tooltip << '\n' << _("Liminal units: ") << utils::signed_percent(c);
|
||||
|
||||
std::string tod_image = tod.image;
|
||||
if (tod.lawful_bonus_modified > 0) tod_image += "~BRIGHTEN()";
|
||||
else if (tod.lawful_bonus_modified < 0) tod_image += "~DARKEN()";
|
||||
if (preferences::flip_time()) tod_image += "~FL(horiz)";
|
||||
|
||||
return report("", tod_image, tooltip.str(), "time_of_day");
|
||||
}
|
||||
|
||||
static report report_turn(const report_data &)
|
||||
{
|
||||
std::ostringstream str;
|
||||
str << resources::tod_manager->turn();
|
||||
int nb = resources::tod_manager->number_of_turns();
|
||||
if (nb != -1) str << '/' << nb;
|
||||
return report(str.str());
|
||||
}
|
||||
|
||||
static report report_gold(const report_data &data)
|
||||
{
|
||||
std::ostringstream str;
|
||||
// Suppose the full/"pathfind" unit map is applied.
|
||||
int fake_gold = (*resources::teams)[data.viewing_side - 1].gold() -
|
||||
resources::whiteboard->get_spent_gold_for(data.current_side);
|
||||
char const *end = naps;
|
||||
if (data.current_side != data.active_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
else if (fake_gold < 0)
|
||||
str << span_color(font::BAD_COLOR);
|
||||
else
|
||||
end = "";
|
||||
str << fake_gold << end;
|
||||
return report(str.str());
|
||||
}
|
||||
|
||||
static report report_villages(const report_data &data)
|
||||
{
|
||||
std::ostringstream str;
|
||||
const team &viewing_team = (*resources::teams)[data.viewing_side - 1];
|
||||
team_data td = calculate_team_data(viewing_team, data.current_side);
|
||||
str << td.villages << '/';
|
||||
if (viewing_team.uses_shroud()) {
|
||||
int unshrouded_villages = 0;
|
||||
foreach (const map_location &loc, resources::game_map->villages()) {
|
||||
if (!viewing_team.shrouded(loc))
|
||||
++unshrouded_villages;
|
||||
}
|
||||
str << unshrouded_villages;
|
||||
} else {
|
||||
str << resources::game_map->villages().size();
|
||||
}
|
||||
return gray_inactive(data, str.str());
|
||||
}
|
||||
|
||||
static report report_num_units(const report_data &data)
|
||||
{
|
||||
return gray_inactive(data, str_cast(side_units(data.current_side)));
|
||||
}
|
||||
|
||||
static report report_upkeep(const report_data &data)
|
||||
{
|
||||
std::ostringstream str;
|
||||
const team &viewing_team = (*resources::teams)[data.viewing_side - 1];
|
||||
team_data td = calculate_team_data(viewing_team, data.current_side);
|
||||
str << td.expenses << " (" << td.upkeep << ")";
|
||||
return gray_inactive(data, str.str());
|
||||
}
|
||||
|
||||
static report report_expenses(const report_data &data)
|
||||
{
|
||||
const team &viewing_team = (*resources::teams)[data.viewing_side - 1];
|
||||
team_data td = calculate_team_data(viewing_team, data.current_side);
|
||||
return gray_inactive(data, str_cast(td.expenses));
|
||||
}
|
||||
|
||||
static report report_income(const report_data &data)
|
||||
{
|
||||
std::ostringstream str;
|
||||
const team &viewing_team = (*resources::teams)[data.viewing_side - 1];
|
||||
team_data td = calculate_team_data(viewing_team, data.current_side);
|
||||
char const *end = naps;
|
||||
if (data.current_side != data.active_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
else if (td.net_income < 0)
|
||||
str << span_color(font::BAD_COLOR);
|
||||
else
|
||||
end = "";
|
||||
str << td.net_income << end;
|
||||
return report(str.str());
|
||||
}
|
||||
|
||||
static report report_terrain(const report_data &data)
|
||||
{
|
||||
gamemap &map = *resources::game_map;
|
||||
const team &viewing_team = (*resources::teams)[data.viewing_side - 1];
|
||||
if (!map.on_board(data.mouseover_hex) || viewing_team.shrouded(data.mouseover_hex))
|
||||
return report();
|
||||
|
||||
t_translation::t_terrain terrain = map.get_terrain(data.mouseover_hex);
|
||||
if (terrain == t_translation::OFF_MAP_USER)
|
||||
return report();
|
||||
|
||||
std::ostringstream str;
|
||||
if (map.is_village(data.mouseover_hex))
|
||||
{
|
||||
int owner = village_owner(data.mouseover_hex, *resources::teams) + 1;
|
||||
if (owner == 0 || viewing_team.fogged(data.mouseover_hex)) {
|
||||
str << map.get_terrain_info(terrain).income_description();
|
||||
} else if (owner == data.current_side) {
|
||||
str << map.get_terrain_info(terrain).income_description_own();
|
||||
} else if (viewing_team.is_enemy(owner)) {
|
||||
str << map.get_terrain_info(terrain).income_description_enemy();
|
||||
} else {
|
||||
str << map.get_terrain_info(terrain).income_description_ally();
|
||||
}
|
||||
str << ' ';
|
||||
} else {
|
||||
str << map.get_terrain_info(terrain).description();
|
||||
}
|
||||
|
||||
const t_translation::t_list &underlying = map.underlying_union_terrain(terrain);
|
||||
if (underlying.size() != 1 || underlying.front() != terrain)
|
||||
{
|
||||
str << " (";
|
||||
for (t_translation::t_list::const_iterator i = underlying.begin(),
|
||||
i_end = underlying.end(); i != i_end; ++i)
|
||||
{
|
||||
str << map.get_terrain_info(*i).name();
|
||||
if (i + 1 != underlying.end()) {
|
||||
str << ", ";
|
||||
}
|
||||
}
|
||||
str << ')';
|
||||
}
|
||||
return report(str.str());
|
||||
}
|
||||
|
||||
static report report_position(const report_data &data)
|
||||
{
|
||||
gamemap &map = *resources::game_map;
|
||||
if (!map.on_board(data.mouseover_hex))
|
||||
return report();
|
||||
t_translation::t_terrain terrain = map[data.mouseover_hex];
|
||||
if (terrain == t_translation::OFF_MAP_USER)
|
||||
return report();
|
||||
|
||||
std::ostringstream str;
|
||||
str << data.mouseover_hex;
|
||||
|
||||
const unit *u = get_visible_unit(data);
|
||||
const team &viewing_team = (*resources::teams)[data.viewing_side - 1];
|
||||
if (!u ||
|
||||
(data.displayed_unit_hex != data.mouseover_hex &&
|
||||
data.displayed_unit_hex != data.selected_hex) ||
|
||||
viewing_team.shrouded(data.mouseover_hex))
|
||||
return report(str.str());
|
||||
|
||||
int move_cost = u->movement_cost(terrain);
|
||||
int defense = 100 - u->defense_modifier(terrain);
|
||||
if (move_cost < unit_movement_type::UNREACHABLE) {
|
||||
str << " (" << defense << "%," << move_cost << ')';
|
||||
} else if (data.mouseover_hex == data.displayed_unit_hex) {
|
||||
str << " (" << defense << "%,-)";
|
||||
} else {
|
||||
str << " (-)";
|
||||
}
|
||||
return report(str.str());
|
||||
}
|
||||
|
||||
static report report_side_playing(const report_data &data)
|
||||
{
|
||||
const team &active_team = (*resources::teams)[data.active_side - 1];
|
||||
std::string flag_icon = active_team.flag_icon();
|
||||
std::string old_rgb = game_config::flag_rgb;
|
||||
std::string new_rgb = team::get_side_color_index(data.active_side);
|
||||
std::string mods = "~RC(" + old_rgb + ">" + new_rgb + ")";
|
||||
if (flag_icon.empty())
|
||||
flag_icon = game_config::images::flag_icon;
|
||||
image::locator flag_icon_img(flag_icon, mods);
|
||||
return report("", flag_icon_img, active_team.current_player());
|
||||
}
|
||||
|
||||
static report report_observers(const report_data &data)
|
||||
{
|
||||
if (data.observers.empty())
|
||||
return report();
|
||||
|
||||
std::ostringstream str;
|
||||
str << _("Observers:") << '\n';
|
||||
foreach (const std::string &obs, data.observers) {
|
||||
str << obs << '\n';
|
||||
}
|
||||
return report("", game_config::images::observer, str.str());
|
||||
}
|
||||
|
||||
#ifdef DISABLE_EDITOR
|
||||
static report report_editor_selected_terrain(const report_data &)
|
||||
{
|
||||
return report();
|
||||
}
|
||||
|
||||
static report report_editor_left_button_function(const report_data &)
|
||||
{
|
||||
return report();
|
||||
}
|
||||
#else
|
||||
namespace editor {
|
||||
extern std::string selected_terrain, left_button_function;
|
||||
}
|
||||
|
||||
static report report_editor_selected_terrain(const report_data &)
|
||||
{
|
||||
if (editor::selected_terrain.empty())
|
||||
return report();
|
||||
else
|
||||
return report(editor::selected_terrain);
|
||||
}
|
||||
|
||||
static report report_editor_left_button_function(const report_data &)
|
||||
{
|
||||
if (editor::left_button_function.empty())
|
||||
return report();
|
||||
else
|
||||
return report(editor::left_button_function);
|
||||
}
|
||||
#endif
|
||||
|
||||
static report report_clock(const report_data &)
|
||||
{
|
||||
time_t t = std::time(NULL);
|
||||
struct tm *lt = std::localtime(&t);
|
||||
if (!lt) return report();
|
||||
char temp[10];
|
||||
size_t s = std::strftime(temp, 10, preferences::clock_format().c_str(), lt);
|
||||
if (!s) return report();
|
||||
return report(temp);
|
||||
}
|
||||
|
||||
static report report_countdown(const report_data &data)
|
||||
{
|
||||
const team &viewing_team = (*resources::teams)[data.viewing_side - 1];
|
||||
int min, sec;
|
||||
if (viewing_team.countdown_time() == 0)
|
||||
return report_clock(data);
|
||||
std::ostringstream str;
|
||||
sec = viewing_team.countdown_time() / 1000;
|
||||
char const *end = naps;
|
||||
if (data.current_side != data.active_side)
|
||||
str << span_color(font::GRAY_COLOR);
|
||||
else if (sec < 60)
|
||||
str << "<span foreground=\"#c80000\">";
|
||||
else if (sec < 120)
|
||||
str << "<span foreground=\"#c8c800\">";
|
||||
else
|
||||
end = "";
|
||||
min = sec / 60;
|
||||
str << min << ':';
|
||||
sec = sec % 60;
|
||||
if (sec < 10) str << '0';
|
||||
str << sec << end;
|
||||
return report(str.str());
|
||||
}
|
||||
|
||||
report reports::generate_report(TYPE type, const report_data & data)
|
||||
{
|
||||
switch(type) {
|
||||
case UNIT_NAME:
|
||||
return report_unit_name(data);
|
||||
case UNIT_TYPE:
|
||||
return report_unit_type(data);
|
||||
case UNIT_RACE:
|
||||
return report_unit_race(data);
|
||||
case UNIT_SIDE:
|
||||
return report_unit_side(data);
|
||||
case UNIT_LEVEL:
|
||||
return report_unit_level(data);
|
||||
case UNIT_AMLA:
|
||||
return report_unit_amla(data);
|
||||
case UNIT_TRAITS:
|
||||
return report_unit_traits(data);
|
||||
case UNIT_STATUS:
|
||||
return report_unit_status(data);
|
||||
case UNIT_ALIGNMENT:
|
||||
return report_unit_alignment(data);
|
||||
case UNIT_ABILITIES:
|
||||
return report_unit_abilities(data);
|
||||
case UNIT_HP:
|
||||
return report_unit_hp(data);
|
||||
case UNIT_XP:
|
||||
return report_unit_xp(data);
|
||||
case UNIT_ADVANCEMENT_OPTIONS:
|
||||
return report_unit_advancement_options(data);
|
||||
case UNIT_DEFENSE:
|
||||
return report_unit_defense(data);
|
||||
case UNIT_MOVES:
|
||||
return report_unit_moves(data);
|
||||
case UNIT_WEAPONS:
|
||||
return report_unit_weapons(data);
|
||||
case UNIT_IMAGE:
|
||||
return report_unit_image(data);
|
||||
case UNIT_PROFILE:
|
||||
return report_unit_profile(data);
|
||||
case TIME_OF_DAY:
|
||||
return report_time_of_day(data);
|
||||
case TURN:
|
||||
return report_turn(data);
|
||||
case GOLD:
|
||||
return report_gold(data);
|
||||
case VILLAGES:
|
||||
return report_villages(data);
|
||||
case NUM_UNITS:
|
||||
return report_num_units(data);
|
||||
case UPKEEP:
|
||||
return report_upkeep(data);
|
||||
case EXPENSES:
|
||||
return report_expenses(data);
|
||||
case INCOME:
|
||||
return report_income(data);
|
||||
case TERRAIN:
|
||||
return report_terrain(data);
|
||||
case POSITION:
|
||||
return report_position(data);
|
||||
case SIDE_PLAYING:
|
||||
return report_side_playing(data);
|
||||
case OBSERVERS:
|
||||
return report_observers(data);
|
||||
case EDITOR_SELECTED_TERRAIN:
|
||||
return report_editor_selected_terrain(data);
|
||||
case EDITOR_LEFT_BUTTON_FUNCTION:
|
||||
return report_editor_left_button_function(data);
|
||||
case REPORT_COUNTDOWN:
|
||||
return report_countdown(data);
|
||||
case REPORT_CLOCK:
|
||||
return report_clock(data);
|
||||
default:
|
||||
assert(false);
|
||||
return report();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,12 +91,21 @@ namespace reports {
|
|||
const std::string& tooltip, const std::string& action="");
|
||||
};
|
||||
|
||||
report generate_report(TYPE type,
|
||||
const team &viewing_team,
|
||||
int current_side, int active_side,
|
||||
const map_location& loc, const map_location& mouseover, const map_location& displayed_unit_hex,
|
||||
const std::set<std::string> &observers,
|
||||
const config& level, bool show_everything = false);
|
||||
struct report_data
|
||||
{
|
||||
int viewing_side;
|
||||
int current_side;
|
||||
int active_side;
|
||||
map_location selected_hex;
|
||||
map_location mouseover_hex;
|
||||
map_location displayed_unit_hex;
|
||||
const std::set<std::string> &observers;
|
||||
const config &level;
|
||||
bool show_everything;
|
||||
};
|
||||
|
||||
report generate_report(TYPE type, const report_data &data);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue