43 #include <boost/dynamic_bitset.hpp> 44 #include <boost/format.hpp> 45 #include <boost/lexical_cast.hpp> 48 const std::string &tooltip,
const std::string &
help =
"")
51 element[
"text"] = text;
52 if (!tooltip.empty()) element[
"tooltip"] = tooltip;
53 if (!
help.empty()) element[
"help"] =
help;
57 const std::string &tooltip,
const std::string &
help =
"")
60 element[
"image"] = image;
61 if (!tooltip.empty()) element[
"tooltip"] = tooltip;
62 if (!
help.empty()) element[
"help"] =
help;
66 const std::string &tooltip =
"",
const std::string &
help =
"")
74 const std::string &tooltip =
"",
const std::string &
help =
"")
84 char const *
path,
char const *desc1,
char const *desc2)
91 static std::string
flush(std::ostringstream &
s)
93 std::string r(s.str());
104 }
else if (viewing_team.
fogged(hex)) {
123 #define REPORT_GENERATOR(n, cn) \ 124 static config report_##n(reports::context & cn); \ 125 static report_generator_helper reg_gen_##n(#n, &report_##n); \ 126 static config report_##n(reports::context & cn) 128 static char const *
naps =
"</span>";
170 std::ostringstream str, tooltip;
171 str <<
"<b>" << name <<
"</b>";
172 tooltip <<
_(
"Name: ") <<
"<b>" << name <<
"</b>";
191 std::ostringstream str, tooltip;
193 tooltip <<
_(
"Type: ") <<
"<b>" << u->
type_name() <<
"</b>\n" 195 return text_report(str.str(), tooltip.str(), has_variations_prefix +
"unit_" + u->
type_id());
211 std::ostringstream str, tooltip;
213 tooltip <<
_(
"Race: ") <<
"<b>" << u->
race()->
name(u->
gender()) <<
"</b>";
232 return VGETTEXT(
"Side: <b>$side_name</b> ($color_name)",
245 std::string new_rgb = u_team.
color();
246 std::string mods =
"~RC(" + old_rgb +
">" + new_rgb +
")";
247 if (flag_icon.empty())
250 std::stringstream text;
251 text <<
" " << u->
side();
254 add_image(report, flag_icon + mods, tooltip,
"");
255 add_text(report, text.str(), tooltip,
"");
290 typedef std::pair<std::string, std::string> pair_string;
291 for (
const pair_string &ps : u->
amla_icons()) {
301 const std::vector<t_string> &traits = u->
trait_names();
304 unsigned nb = traits.size();
305 for (
unsigned i = 0;
i < nb; ++
i)
307 std::ostringstream str, tooltip;
309 if (
i != nb - 1 ) str <<
", ";
310 tooltip <<
_(
"Trait: ") <<
"<b>" << traits[
i] <<
"</b>\n" 312 add_text(res, str.str(), tooltip.str(),
"traits_" + trait_ids[
i]);
333 add_status(res,
"misc/invisible.png",
N_(
"invisible: "),
334 N_(
"This unit is invisible. It cannot be seen or attacked by enemy units."));
338 N_(
"This unit has been slowed. It will only deal half its normal damage when attacking and its movement cost is doubled."));
342 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."));
345 add_status(res,
"misc/petrified.png",
N_(
"petrified: "),
346 N_(
"This unit has been petrified. It may not move or attack."));
364 std::ostringstream str, tooltip;
366 const std::string align_id = u->
alignment().to_string();
377 tooltip <<
_(
"Alignment: ") <<
"<b>" << align <<
"</b>\n" 380 return text_report(str.str(), tooltip.str(),
"time_of_day");
385 const map_location& mouseover_hex = rc.screen().mouseover_hex();
386 const map_location& displayed_unit_hex = rc.screen().displayed_unit_hex();
387 const map_location& hex = mouseover_hex.
valid() ? mouseover_hex : displayed_unit_hex;
404 boost::dynamic_bitset<> active;
405 const std::vector<std::tuple<std::string, t_string,t_string,t_string>> &abilities = u->
ability_tooltips(active, loc);
406 const std::size_t abilities_size = abilities.size();
407 for ( std::size_t
i = 0;
i != abilities_size; ++
i )
410 const std::string&
id = std::get<0>(abilities[
i]);
411 const std::string&
base_name = std::get<1>(abilities[
i]).base_str();
412 const t_string& display_name = std::get<2>(abilities[
i]);
413 const t_string& description = std::get<3>(abilities[
i]);
415 std::ostringstream str, tooltip;
421 if ( i + 1 != abilities_size )
424 tooltip <<
_(
"Ability: ") <<
"<b>" << display_name <<
"</b>";
426 tooltip <<
"<i>" <<
_(
" (inactive)") <<
"</i>";
427 tooltip <<
'\n' << description;
436 const map_location& mouseover_hex = rc.screen().mouseover_hex();
444 const map_location& mouseover_hex = rc.screen().mouseover_hex();
446 if(visible_unit && u && visible_unit->
id() != u->
id() && mouseover_hex.
valid())
456 std::ostringstream str, tooltip;
460 std::set<std::string> resistances_table;
462 bool att_def_diff =
false;
466 std::ostringstream line;
472 if (res_att == res_def) {
483 resistances_table.insert(line.str());
486 tooltip <<
_(
"Resistances: ");
488 tooltip <<
_(
"(Att / Def)");
490 for (
const std::string &line : resistances_table) {
509 std::ostringstream str, tooltip;
519 tooltip <<
_(
"Experience Modifier: ") << exp_mod <<
'%';
559 std::ostringstream str, tooltip;
572 if (underlyings.size() != 1 || underlyings.front() != terrain)
585 <<
span_color(t_color) << t_def <<
'%' << naps
586 << (revert ?
_(
"maximum^max.") :
_(
"minimum^min.")) <<
'\n';
591 tooltip <<
"<b>" <<
_(
"Defense: ") <<
span_color(color) << def <<
'%' << naps <<
"</b>";
597 const team &viewing_team = rc.teams()[rc.screen().viewing_team()];
598 const map_location& mouseover_hex = rc.screen().mouseover_hex();
599 const map_location& displayed_unit_hex = rc.screen().displayed_unit_hex();
600 const map_location& hex = (mouseover_hex.
valid() && !viewing_team.
shrouded(mouseover_hex)) ? mouseover_hex : displayed_unit_hex;
607 if(attack_indicator_src.
valid())
610 const map_location& mouseover_hex = rc.screen().mouseover_hex();
612 if(visible_unit && u && visible_unit->
id() != u->
id() && mouseover_hex.
valid())
623 std::ostringstream str, tooltip;
625 str <<
_(
"vision:") <<
' ' << u->
vision();
626 tooltip <<
_(
"vision:") <<
' ' << u->
vision() <<
'\n';
629 if (static_cast<std::streamoff>(str.tellp()) == 0)
630 str <<
_(
"jamming:") <<
' ' << u->
jamming();
631 tooltip <<
_(
"jamming:") <<
' ' << u->
jamming() <<
'\n';
649 std::ostringstream str, tooltip;
650 double movement_frac = 1.0;
652 std::set<terrain_movement> terrain_moves;
656 if (movement_frac > 1.0)
660 tooltip <<
_(
"Movement Costs:") <<
"\n";
673 tooltip << tm.name <<
": ";
680 else if (tm.moves > 1)
684 tooltip <<
"<span foreground=\"" << color <<
"\">";
692 tooltip <<
naps <<
'\n';
695 int grey = 128 +
static_cast<int>((255 - 128) * movement_frac);
698 if(is_visible_unit) {
700 if(route.
steps.size() > 0) {
709 const auto& end = route.
marks.find(route.
steps.back());
710 if(end != route.
marks.end() && end->second.capture) {
742 std::ostringstream str, tooltip;
745 struct string_with_tooltip {
752 int base_damage = at.
damage();
754 int damage_multiplier = 100;
757 damage_multiplier += tod_bonus;
759 if (leader_bonus != 0)
760 damage_multiplier += leader_bonus;
763 int damage_divisor = slowed ? 20000 : 10000;
765 damage =
round_damage(specials_damage, damage_multiplier * 100, damage_divisor);
769 unsigned cur_hp = std::min<unsigned>(std::max(0, u.
hitpoints()), max_hp);
772 unsigned min_attacks, max_attacks;
774 unsigned num_attacks =
swarm_blows(min_attacks, max_attacks, cur_hp, max_hp);
777 if ( damage > specials_damage )
779 else if ( damage < specials_damage )
785 tooltip <<
_(
"Weapon: ") <<
"<b>" << at.
name() <<
"</b>\n" 786 <<
_(
"Damage: ") <<
"<b>" << damage <<
"</b>\n";
788 if ( tod_bonus || leader_bonus || slowed || specials_damage != base_damage )
790 tooltip <<
'\t' <<
_(
"Base damage: ") << base_damage <<
'\n';
791 if ( specials_damage != base_damage ) {
792 tooltip <<
'\t' <<
_(
"With specials: ") << specials_damage <<
'\n';
795 tooltip <<
'\t' <<
_(
"Time of day: ")
799 tooltip <<
'\t' <<
_(
"Leadership: ")
803 tooltip <<
'\t' <<
_(
"Slowed: ") <<
"/ 2" <<
'\n';
807 tooltip <<
_(
"Attacks: ") <<
"<b>" << num_attacks <<
"</b>\n";
808 if ( max_attacks != min_attacks && cur_hp != max_hp ) {
809 if ( max_attacks < min_attacks ) {
811 tooltip <<
'\t' <<
_(
"Max swarm bonus: ") << (min_attacks-max_attacks) <<
'\n';
812 tooltip <<
'\t' <<
_(
"Swarm: ") <<
"* "<< (100 - cur_hp*100/max_hp) <<
"%\n";
813 tooltip <<
'\t' <<
_(
"Base attacks: ") <<
'+' << base_attacks <<
'\n';
817 if ( max_attacks != base_attacks ) {
818 int attack_diff =
static_cast<int>(max_attacks) - static_cast<int>(base_attacks);
824 tooltip <<
'\t' <<
_(
"Base attacks: ") << base_attacks <<
'\n';
825 if ( max_attacks != base_attacks ) {
826 tooltip <<
'\t' <<
_(
"With specials: ") << max_attacks <<
'\n';
828 if ( min_attacks != 0 ) {
829 tooltip <<
'\t' <<
_(
"Subject to swarm: ") << (max_attacks-min_attacks) <<
'\n';
831 tooltip <<
'\t' <<
_(
"Swarm: ") <<
"* "<< (cur_hp*100/max_hp) <<
"%\n";
834 else if ( num_attacks != base_attacks ) {
835 tooltip <<
'\t' <<
_(
"Base attacks: ") << base_attacks <<
'\n';
836 tooltip <<
'\t' <<
_(
"With specials: ") << num_attacks <<
'\n';
839 const string_with_tooltip damage_and_num_attacks {
flush(str),
flush(tooltip)};
845 const std::string range_png = std::string(
"icons/profiles/") + at.
range() +
"_attack.png~SCALE_INTO_SHARP(16,16)";
846 const std::string type_png = std::string(
"icons/profiles/") + at.
type() +
".png~SCALE_INTO_SHARP(16,16)";
850 if(!range_png_exists || !type_png_exists) {
853 << lang_type <<
"</span>\n";
856 tooltip <<
_(
"Weapon range: ") <<
"<b>" << range <<
"</b>\n" 857 <<
_(
"Damage type: ") <<
"<b>" << lang_type <<
"</b>\n" 858 <<
_(
"Damage versus: ") <<
'\n';
862 std::map<int, std::set<std::string>, std::greater<int>> resistances;
863 std::set<std::string> seen_types;
868 if (
enemy.incapacitated())
874 if (!
enemy.is_visible_to_team(viewing_team, see_all))
876 bool new_type = seen_types.insert(
enemy.type_id()).second;
878 int resistance =
enemy.resistance_against(at,
false, loc);
879 resistances[resistance].insert(
enemy.type_name());
883 for (
const auto& resist : resistances) {
884 int damage_with_resistance =
round_damage(specials_damage, damage_multiplier * resist.first, damage_divisor);
885 tooltip <<
"<b>" << damage_with_resistance <<
"</b> " 892 const string_with_tooltip damage_versus {
flush(str),
flush(tooltip)};
898 const std::string attack_icon = at.
icon() +
"~SCALE_INTO_SHARP(60,60)~CROP(2,2,56,56)~SCALE_INTO_SHARP(32,32)";
904 const std::string spacer =
"misc/blank.png~CROP(0, 0, 16, 21)";
905 if (range_png_exists)
add_image(res, spacer +
"~BLIT(" + range_png +
",0,5)", damage_versus.tooltip);
906 if (type_png_exists)
add_image(res, spacer +
"~BLIT(" + type_png +
",0,5)", damage_versus.tooltip);
907 add_text(res, damage_and_num_attacks.str, damage_and_num_attacks.tooltip);
908 add_text(res, damage_versus.str, damage_versus.tooltip);
911 if (!accuracy_parry.empty())
914 <<
" " << accuracy_parry <<
"</span>\n";
917 tooltip <<
_(
"Accuracy:") <<
"<b>" 920 int parry = at.
parry();
922 tooltip <<
_(
"Parry:") <<
"<b>" 933 at.
specials_context(u.shared_from_this(), sec_u->shared_from_this(), hex, sec_u->get_location(), attacking, sec_u_weapon);
935 boost::dynamic_bitset<> active;
936 const std::vector<std::pair<t_string, t_string>> &specials = at.
special_tooltips(&active);
937 const std::size_t specials_size = specials.size();
938 for ( std::size_t
i = 0;
i != specials_size; ++
i )
942 const t_string &description = specials[
i].second;
946 str <<
span_color(details_color) <<
" " <<
" " << name <<
naps <<
'\n';
947 std::string help_page =
"weaponspecial_" + name.
base_str();
948 tooltip <<
_(
"Weapon special: ") <<
"<b>" << name <<
"</b>";
950 tooltip <<
"<i>" <<
_(
" (inactive)") <<
"</i>";
951 tooltip <<
'\n' << description;
955 if(!specials.empty()) {
960 const std::string spacer =
"misc/blank.png~CROP(0, 0, 1, 5)";
973 }
else if(prob < 0.0005) {
976 std::ostringstream res;
977 res << std::setprecision(prob < 0.01 ? 1 : prob < 0.1 ? 2 : 3) << 100.0 * prob <<
"%";
983 std::ostringstream res;
984 res <<
' ' << std::setw(3) << hp;
990 if (!attacker || !defender)
return config();
992 const unit* u = show_attacker ? attacker.get() : defender;
993 const unit* sec_u = !show_attacker ? attacker.get() : defender;
996 std::ostringstream str, tooltip;
999 std::vector<battle_context> weapons;
1000 for (
unsigned int i = 0;
i < attacker->attacks().size();
i++) {
1002 if (attacker->attacks()[
i].attack_weight() > 0) {
1003 weapons.emplace_back(rc.
units(), attacker_pos, defender->
get_location(),
i, -1, 0.0,
nullptr, attacker);
1010 combatant attacker_combatant(weapon.get_attacker_stats());
1011 combatant defender_combatant(weapon.get_defender_stats());
1012 attacker_combatant.
fight(defender_combatant);
1015 show_attacker ? weapon.get_attacker_stats() : weapon.get_defender_stats();
1017 !show_attacker ? weapon.get_attacker_stats() : weapon.get_defender_stats();
1019 int total_damage = 0;
1020 int base_damage = 0;
1022 int chance_to_hit = 0;
1023 t_string weapon_name =
_(
"weapon^None");
1026 if (context_unit_stats.
weapon) {
1027 base_damage =
attack_info(rc, *context_unit_stats.
weapon, res, *u, unit_loc, sec_u, other_context_unit_stats.
weapon);
1028 total_damage = context_unit_stats.
damage;
1029 num_blows = context_unit_stats.
num_blows;
1031 weapon_name = context_unit_stats.
weapon->name();
1033 if ( total_damage > base_damage )
1035 else if ( total_damage < base_damage )
1039 tooltip <<
_(
"Weapon: ") <<
"<b>" << weapon_name <<
"</b>\n" 1040 <<
_(
"Damage: ") <<
"<b>" <<
"0" <<
"</b>\n";
1048 <<
" (" <<
span_color(chance_color) << chance_to_hit <<
"%" <<
naps <<
")" 1051 tooltip <<
_(
"Weapon: ") <<
"<b>" << weapon_name <<
"</b>\n" 1052 <<
_(
"Total damage") <<
"<b>" << total_damage <<
"</b>\n";
1055 std::vector<std::pair<int, double>> hp_prob_vector;
1058 std::vector<std::pair<double, int>> prob_hp_vector;
1061 combatant*
c = show_attacker ? &attacker_combatant : &defender_combatant;
1063 for(i = 0; i < static_cast<int>(c->
hp_dist.size()); i++) {
1068 prob_hp_vector.emplace_back(prob, i);
1071 std::sort(prob_hp_vector.begin(), prob_hp_vector.end());
1074 int max_hp_distrib_rows_ = 10;
1077 int nb_elem = std::min<int>(max_hp_distrib_rows_, prob_hp_vector.size());
1079 for(i = prob_hp_vector.size() - nb_elem;
1080 i < static_cast<int>(prob_hp_vector.size()); i++) {
1082 hp_prob_vector.emplace_back(prob_hp_vector[i].second, prob_hp_vector[i].first);
1086 std::sort(hp_prob_vector.begin(), hp_prob_vector.end());
1088 std::reverse(hp_prob_vector.begin(), hp_prob_vector.end());
1090 for(i = 0; i < static_cast<int>(hp_prob_vector.size()); i++) {
1092 int hp = hp_prob_vector[
i].first;
1093 double prob = hp_prob_vector[
i].second;
1115 if ((u !=
nullptr) && (!u->
attacks().empty())) {
1116 const std::string attack_headline =
_n(
"Attack",
"Attacks", u->
attacks().size());
1119 + attack_headline +
"</span>" +
'\n',
"");
1124 const std::string line =
VGETTEXT(
"Remaining: $left/$max",
1125 {{
"left", std::to_string(
left)},
1126 {
"max", std::to_string(max)}});
1128 _(
"This unit can attack multiple times per turn."));
1141 const map_location& mouseover_hex = rc.screen().mouseover_hex();
1142 const map_location& displayed_unit_hex = rc.screen().displayed_unit_hex();
1143 const map_location& hex = mouseover_hex.
valid() ? mouseover_hex : displayed_unit_hex;
1153 if (!u)
return report_unit_weapons(rc);
1154 if (!sec_u || u.get() == sec_u)
return unit_weapons(rc, sec_u, rc.screen().mouseover_hex());
1156 map_location highlighted_hex = rc.screen().displayed_unit_hex();
1159 attack_loc = rc.mhb()->current_unit_attacks_from(highlighted_hex);
1161 if (!attack_loc.
valid())
1162 return unit_weapons(rc, sec_u, rc.screen().mouseover_hex());
1173 if (!sec_u || u.get() == sec_u)
return unit_weapons(rc, u.get(), u->get_location());
1175 map_location highlighted_hex = rc.screen().displayed_unit_hex();
1178 attack_loc = rc.mhb()->current_unit_attacks_from(highlighted_hex);
1180 if (!attack_loc.
valid())
1214 std::ostringstream tooltip;
1215 std::ostringstream text;
1218 const std::vector<time_of_day>& schedule = rc.
tod().
times(tod_schedule_hex);
1220 tooltip <<
_(
"Time of day schedule:") <<
" \n";
1224 if (i == current) tooltip <<
"<big><b>";
1225 tooltip << tod.name <<
"\n";
1226 if (i == current) tooltip <<
"</b></big>";
1230 int times = schedule.size();
1231 text << current + 1 <<
"/" << times;
1233 return text_report(text.str(), tooltip.str(),
"..schedule");
1237 map_location mouseover_hex = rc.screen().mouseover_hex();
1253 std::ostringstream tooltip;
1258 std::string lawful_color(
"white");
1259 std::string chaotic_color(
"white");
1260 std::string liminal_color(
"white");
1264 lawful_color = (b > 0) ?
"green" :
"red";
1265 chaotic_color = (b < 0) ?
"green" :
"red";
1268 liminal_color = (l > 0) ?
"green" :
"red";
1270 tooltip <<
_(
"Time of day:") <<
" <b>" << tod.
name <<
"</b>\n" 1271 <<
_(
"Lawful units: ") <<
"<span foreground=\"" << lawful_color <<
"\">" 1274 <<
_(
"Chaotic units: ") <<
"<span foreground=\"" << chaotic_color <<
"\">" 1276 <<
_(
"Liminal units: ") <<
"<span foreground=\"" << liminal_color <<
"\">" 1279 std::string tod_image = tod.
image;
1286 return image_report(tod_image, tooltip.str(),
"time_of_day_" + tod.
id);
1290 map_location mouseover_hex = rc.screen().mouseover_hex();
1306 std::ostringstream tooltip;
1313 std::string lawful_color(
"white");
1314 std::string chaotic_color(
"white");
1315 std::string liminal_color(
"white");
1318 lawful_color = (bonus > 0) ?
"green" :
"red";
1319 chaotic_color = (bonus < 0) ?
"green" :
"red";
1322 liminal_color = (l > 0) ?
"green" :
"red";
1324 tooltip << local_tod.
name <<
'\n' 1325 <<
_(
"Lawful units: ") <<
"<span foreground=\"" << lawful_color <<
"\">" 1328 <<
_(
"Chaotic units: ") <<
"<span foreground=\"" << chaotic_color <<
"\">" 1330 <<
_(
"Liminal units: ") <<
"<span foreground=\"" << liminal_color <<
"\">" 1333 std::string local_tod_image =
"themes/classic/" + local_tod.
image;
1334 std::string global_tod_image =
"themes/classic/" + global_tod.
image;
1336 local_tod_image +=
"~BLIT(";
1339 local_tod_image +=
")";
1354 std::string bg_terrain_image;
1358 bg_terrain_image =
"~BLIT(unit_env/terrain/terrain-" + terrain_id +
".png)" + bg_terrain_image;
1361 std::stringstream color;
1362 color << local_tod.
color;
1364 bg_terrain_image = bg_terrain_image +
"~CS(" + color.str() +
")";
1367 std::string unit_image;
1371 std::string tod_image = global_tod_image +
"~BLIT(" + local_tod_image +
")";
1373 return image_report(tod_image + bg_terrain_image + unit_image, tooltip.str(),
"time_of_day");
1377 map_location mouseover_hex = rc.screen().mouseover_hex();
1384 std::ostringstream str, tooltip;
1385 str << rc.tod().turn();
1386 int nb = rc.tod().number_of_turns();
1387 if (nb != -1) str <<
'/' << nb;
1389 tooltip <<
_(
"Turn Number");
1391 tooltip <<
"\n\n" <<
_(
"When the game exceeds the number of turns indicated by the second number, it will end.");
1398 std::ostringstream str;
1399 int viewing_side = rc.screen().viewing_side();
1401 int fake_gold = rc.dc().get_team(viewing_side).gold();
1404 fake_gold -= rc.wb()->get_spent_gold_for(viewing_side);
1405 char const *end =
naps;
1406 if (viewing_side != rc.screen().playing_side()) {
1409 else if (fake_gold < 0) {
1416 return text_report(str.str(),
_(
"Gold") +
"\n\n" +
_(
"The amount of gold currently available to recruit and maintain your army."));
1421 std::ostringstream str;
1422 int viewing_side = rc.screen().viewing_side();
1423 const team &viewing_team = rc.dc().get_team(viewing_side);
1424 str << viewing_team.
villages().size() <<
'/';
1426 int unshrouded_villages = 0;
1429 ++unshrouded_villages;
1431 str << unshrouded_villages;
1433 str << rc.map().villages().size();
1435 return gray_inactive(rc,str.str(),
_(
"Villages") +
"\n\n" +
_(
"The fraction of known villages that your side has captured."));
1440 return gray_inactive(rc, std::to_string(rc.dc().side_units(rc.screen().viewing_side())),
_(
"Units") +
"\n\n" +
_(
"The total number of units on your side."));
1445 std::ostringstream str;
1446 int viewing_side = rc.screen().viewing_side();
1447 const team &viewing_team = rc.dc().get_team(viewing_side);
1449 str << td.
expenses <<
" (" << td.upkeep <<
")";
1450 return gray_inactive(rc,str.str(),
_(
"Upkeep") +
"\n\n" +
_(
"The expenses incurred at the end of every turn to maintain your army. The first number is the amount of gold that will be deducted. It is equal to the number of unit levels not supported by villages. The second is the total cost of upkeep, including that covered by villages — in other words, the amount of gold that would be deducted if you lost all villages."));
1455 int viewing_side = rc.screen().viewing_side();
1456 const team &viewing_team = rc.dc().get_team(viewing_side);
1463 std::ostringstream str;
1464 int viewing_side = rc.screen().viewing_side();
1465 const team &viewing_team = rc.dc().get_team(viewing_side);
1467 char const *end =
naps;
1468 if (viewing_side != rc.screen().playing_side()) {
1469 if (td.net_income < 0) {
1470 td.net_income = - td.net_income;
1478 else if (td.net_income < 0) {
1479 td.net_income = - td.net_income;
1486 str << td.net_income << end;
1487 return text_report(str.str(),
_(
"Net Income") +
"\n\n" +
_(
"The net amount of gold you gain or lose each turn, taking into account income from controlled villages and payment of upkeep."));
1491 void blit_tced_icon(
config &cfg,
const std::string &terrain_id,
const std::string &icon_image,
bool high_res,
1492 const std::string &terrain_name) {
1493 const std::string tc_base = high_res ?
"images/buttons/icon-base-32.png" :
"images/buttons/icon-base-16.png";
1494 const std::string terrain_image =
"terrain/" + icon_image + (high_res ?
"_30.png" :
".png");
1495 add_image(cfg, tc_base +
"~RC(magenta>" + terrain_id +
")~BLIT(" + terrain_image +
")", terrain_name);
1501 const gamemap &map = rc.map();
1502 map_location mouseover_hex = rc.screen().mouseover_hex();
1505 mouseover_hex = rc.screen().selected_hex();
1516 bool high_res =
false;
1538 if (terrain_icon.empty())
1540 blit_tced_icon(cfg, terrain_id, terrain_icon, high_res, terrain_name);
1547 const gamemap &map = rc.map();
1548 int viewing_side = rc.screen().viewing_side();
1549 const team &viewing_team = rc.dc().get_team(viewing_side);
1550 map_location mouseover_hex = rc.screen().mouseover_hex();
1558 std::ostringstream str;
1561 int owner = rc.dc().village_owner(mouseover_hex);
1562 if (owner == 0 || viewing_team.
fogged(mouseover_hex)) {
1564 }
else if (owner == viewing_side) {
1566 }
else if (viewing_team.
is_enemy(owner)) {
1573 if(!underlying_desc.empty()) {
1574 str << underlying_desc;
1585 std::ostringstream text;
1586 std::ostringstream tooltip;
1587 std::ostringstream
help;
1589 text << static_cast<int>(rc.screen().get_zoom_factor() * 100) <<
"%";
1591 return text_report(text.str(), tooltip.str(), help.str());
1596 const gamemap &map = rc.map();
1597 map_location mouseover_hex = rc.screen().mouseover_hex(),
1598 displayed_unit_hex = rc.screen().displayed_unit_hex(),
1599 selected_hex = rc.screen().selected_hex();
1601 if (!map.
on_board(mouseover_hex)) {
1605 mouseover_hex = selected_hex;
1613 std::ostringstream str;
1614 str << mouseover_hex;
1617 const team &viewing_team = rc.teams()[rc.screen().viewing_team()];
1619 (displayed_unit_hex != mouseover_hex &&
1620 displayed_unit_hex != rc.screen().selected_hex()) ||
1621 viewing_team.
shrouded(mouseover_hex))
1627 str <<
" " << defense <<
"%," << move_cost;
1628 }
else if (mouseover_hex == displayed_unit_hex) {
1629 str <<
" " << defense <<
"%,‒";
1638 const team &active_team = rc.teams()[rc.screen().playing_team()];
1642 std::string mods =
"~RC(" + old_rgb +
">" + new_rgb +
")";
1643 if (flag_icon.empty())
1650 const std::set<std::string> &observers = rc.screen().observers();
1651 if (observers.empty())
1654 std::ostringstream str;
1655 str <<
_(
"Observers:") <<
'\n';
1656 for (
const std::string &obs : observers) {
1689 std::ostringstream ss;
1695 std::time_t
t = std::time(
nullptr);
1696 ss << std::put_time(std::localtime(&t), format);
1715 int viewing_side = rc.screen().viewing_side();
1716 const team &viewing_team = rc.dc().get_team(viewing_side);
1719 return report_report_clock(rc);
1720 std::ostringstream str;
1722 char const *end =
naps;
1723 if (viewing_side != rc.screen().playing_side())
1726 str <<
"<span foreground=\"#c80000\">";
1728 str <<
"<span foreground=\"#c8c800\">";
1734 if (sec < 10) str <<
'0';
1736 return text_report(str.str(),
_(
"Turn Countdown") +
"\n\n" +
_(
"Countdown until your turn automatically ends."));
1741 dynamic_generators_[
name].reset(g);
1747 dynamic_report_generators::const_iterator
i = dynamic_generators_.find(name);
1748 if (i != dynamic_generators_.end())
1749 return i->second->generate(rc);
1753 return j->second(rc);
1759 if (!all_reports_.empty())
return all_reports_;
1761 all_reports_.insert(v.first);
1763 for (
const dynamic_report_generators::value_type &v : dynamic_generators_) {
1764 all_reports_.insert(v.first);
1766 return all_reports_;
const_attack_ptr weapon
The weapon used by the unit to attack the opponent, or nullptr if there is none.
static config unit_level(const unit *u)
const gamemap & map() const
int attacks_left() const
Gets the remaining number of attacks this unit can perform this turn.
static config unit_xp(const unit *u)
const t_translation::ter_list & underlying_union_terrain(const map_location &loc) const
static std::string _n(const char *str1, const char *str2, int n)
int get_max_liminal_bonus() const
const t_translation::ter_list & underlying_def_terrain(const map_location &loc) const
std::vector< double > hp_dist
Resulting probability distribution (might be not as large as max_hp)
int countdown_time() const
static display * get_singleton()
Returns the display object if a display object exists.
static int get_acceleration()
virtual const map_location & displayed_unit_hex() const
Virtual functions shadowed in game_display.
const team & get_team(int side) const
const t_string & description() const
int jamming() const
Gets the unit's jamming points.
int vision() const
Gets the unit's vision points.
const std::string weapon_details_sep
This class represents a single unit of a specific type.
const std::string & type_id() const
The id of this unit's type.
const color_t inactive_details_color
const std::vector< team > & teams() const
static config time_of_day_at(reports::context &rc, const map_location &mouseover_hex)
tod_color color
The color modifications that should be made to the game board to reflect the time of day...
int movement_cost(const t_translation::terrain_code &terrain) const
Get the unit's movement cost on a particular terrain.
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
const unit * get_visible_unit(const map_location &loc, const team ¤t_team, bool see_all=false) const
static config unit_advancement_options(const unit *u)
std::string get_underlying_terrain_string(const t_translation::terrain_code &terrain) const
const map_location & selected_hex() const
Various functions that implement attacks and attack calculations.
const std::string & id() const
const std::string & side_name() const
bool get_state(const std::string &state) const
Check if the unit is affected by a status effect.
bool terrain_matches(const terrain_code &src, const terrain_code &dest)
Tests whether a specific terrain matches an expression, for matching rules see above.
unit_race::GENDER gender() const
The gender of this unit.
color_t blue_to_white(int val, bool for_text)
const map_location & get_attack_indicator_src()
static const int UNREACHABLE
Magic value that signifies a hex is unreachable.
int hitpoints() const
The current number of hitpoints this unit has.
static void add_status(config &r, char const *path, char const *desc1, char const *desc2)
static int attack_info(reports::context &rc, const attack_type &at, config &res, const unit &u, const map_location &hex, const unit *sec_u=nullptr, const_attack_ptr sec_u_weapon=nullptr)
int get_current_time(const map_location &loc=map_location::null_location()) const
int under_leadership(const unit &u, const map_location &loc, const_attack_ptr weapon, const_attack_ptr opp_weapon)
Tests if the unit at loc is currently affected by leadership.
static config image_report(const std::string &image, const std::string &tooltip="", const std::string &help="")
bool show_everything() const
const std::set< std::string > & report_list()
static std::string format_hp(unsigned hp)
int lawful_bonus
The % bonus lawful units receive.
const color_t good_dmg_color
void modified_attacks(bool is_backstab, unsigned &min_attacks, unsigned &max_attacks) const
Calculates the number of attacks this weapon has, considering specials.
The unit is slowed - it moves slower and does less damage.
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
static config text_report(const std::string &text, const std::string &tooltip="", const std::string &help="")
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
std::string image
The image to be displayed in the game status.
static std::string format_prob(double prob)
The unit is poisoned - it loses health each turn.
std::string absolute_image() const
The name of the file to game_display (used in menus).
const std::string & type() const
bool on_board(const map_location &loc) const
Tell if a location is on the map.
const t_string & income_description() const
int generic_combat_modifier(int lawful_bonus, unit_type::ALIGNMENT alignment, bool is_fearless, int max_liminal_bonus)
Returns the amount that a unit's damage should be multiplied by due to a given lawful_bonus.
static config unit_side(reports::context &rc, const unit *u)
static config unit_name(const unit *u)
const tod_manager & tod() const
static config unit_traits(const unit *u)
report_generator_helper(const char *name, reports::generator_function g)
static config unit_type(const unit *u)
static const color_t attack_info_percent_color(int resistance)
static std::string _(const char *str)
utils::string_map get_base_resistances() const
Gets resistances without any abilities applied.
static config tod_stats_at(reports::context &rc, const map_location &hex)
unsigned int chance_to_hit
Effective chance to hit as a percentage (all factors accounted for).
std::vector< std::tuple< std::string, t_string, t_string, t_string > > ability_tooltips() const
Gets the names and descriptions of this unit's abilities.
A single unit type that the player may recruit.
bool is_nonnull() const
True if this object represents some sentinel values.
std::string get_terrain_string(const map_location &loc) const
const t_string & name(GENDER gender=MALE) const
static config gray_inactive(reports::context &rc, const std::string &str, const std::string &tooltip="")
t_translation::terrain_code get_terrain(const map_location &loc) const
Looks up terrain at a particular location.
const terrain_code VOID_TERRAIN
VOID_TERRAIN is used for shrouded hexes.
const color_t weapon_color
static config unit_abilities(const unit *u, const map_location &loc)
const unit_type & type() const
This unit's type, accounting for gender and variation.
static static_report_generators static_generators
static const t_string get_side_color_name_for_UI(unsigned side)
color_t hp_color() const
Color for this unit's current hitpoints.
std::shared_ptr< const unit > unit_const_ptr
Object which defines a time of day with associated bonuses, image, sounds etc.
static config unit_weapons(reports::context &rc, unit_const_ptr attacker, const map_location &attacker_pos, const unit *defender, bool show_attacker)
static config unit_race(const unit *u)
int defense_modifier(const t_translation::terrain_code &terrain) const
The unit's defense on a given terrain.
std::string span_color(const color_t &color)
Returns a Pango formatting string using the provided color_t object.
This class stores all the data for a single 'side' (in game nomenclature).
Belongs to a non-friendly side; normally visualised by not displaying an orb.
std::string half_signed_value(int val)
Sign with Unicode "−" if negative.
static std::string at(const std::string &file, int line)
const color_t bad_dmg_color
int damage
Effective damage of the weapon (all factors accounted for).
const std::string unicode_minus
static config unit_alignment(reports::context &rc, const unit *u, const map_location &hex)
const std::string & id() const
Gets this unit's id.
const terrain_code FOGGED
#define REPORT_GENERATOR(n, cn)
void register_generator(const std::string &name, generator *)
static const time_of_day get_visible_time_of_day_at(reports::context &rc, const map_location &hex)
const pathfind::marked_route & get_route()
Gets the route along which footsteps are drawn to show movement of a unit.
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
color_t xp_color() const
Color for this unit's XP.
const t_string & name() const
config generate_report(const std::string &name, context &ct, bool only_static=false)
Encapsulates the map of the game.
const t_string & name() const
Gets this unit's translatable display name.
Computes the statistics of a battle between an attacker and a defender unit.
int max_experience() const
The max number of experience points this unit can have.
std::set< t_translation::terrain_code > & encountered_terrains()
const std::string & range() const
bool is_enemy(int n) const
void fight(combatant &opponent, bool levelup_considered=true)
Simulate a fight! Can be called multiple times for cumulative calculations.
std::vector< std::pair< t_string, t_string > > special_tooltips(boost::dynamic_bitset<> *active_list=nullptr) const
Returns a vector of names and descriptions for the specials of *this.
virtual int playing_side() const
int level() const
The current level of this unit.
const std::vector< t_string > & trait_names() const
Gets the names of the currently registered traits.
const std::string & icon() const
static config unit_hp(reports::context &rc, const unit *u)
Structure describing the statistics of a unit involved in the battle.
const t_string & type_name() const
Gets the translatable name of this unit's type.
std::string small_profile() const
An optional profile image to display in Help.
Structure which holds a single route and marks for special events.
const color_t YELLOW_COLOR
const std::string unicode_figure_dash
Generic locator abstracting the location of an image.
std::function< config(reports::context &)> generator_function
static std::string get_side_color_id(unsigned side)
static config unit_status(reports::context &rc, const unit *u)
Encapsulates the map of the game.
static const unit * get_visible_unit(reports::context &rc)
bool shrouded(const map_location &loc) const
Returns true if location (x,y) is covered in shroud.
int round_damage(int base_damage, int bonus, int divisor)
round (base_damage * bonus / divisor) to the closest integer, but up or down towards base_damage ...
unsigned swarm_blows(unsigned min_blows, unsigned max_blows, unsigned hp, unsigned max_hp)
Calculates the number of blows resulting from swarm.
static config unit_box_at(reports::context &rc, const map_location &mouseover_hex)
bool invisible(const map_location &loc, bool see_all=true) const
static std::string side_tooltip(const team &team)
const color_t weapon_details_color
bool shrouded(const map_location &loc) const
const time_of_day get_illuminated_time_of_day(const unit_map &units, const gamemap &map, const map_location &loc, int for_turn=0) const
Returns time of day object for the passed turn at a location.
static std::string gettext(const char *str)
std::string escape_text(const std::string &text)
Escapes the pango markup characters in a text.
const display_context & dc() const
const std::string unicode_en_dash
int max_hitpoints() const
The max number of hitpoints this unit can have.
std::string resistance_color(const int resistance)
static const unit * get_selected_unit(reports::context &rc)
static void add_image(config &report, const std::string &image, const std::string &tooltip, const std::string &help="")
static map_location::DIRECTION s
bool show_variations_in_help() const
Whether the unit type has at least one help-visible variation.
const std::string & flag_icon() const
const unit_map & units() const
t_translation::terrain_code number() const
const std::vector< time_of_day > & times(const map_location &loc=map_location::null_location()) const
const t_string & income_description_own() const
std::string to_hex_string() const
Returns the stored color in rrggbb hex format.
std::string signed_percent(int val)
Convert into a percentage (using the Unicode "−" and +0% convention.
const t_string & income_description_enemy() const
attack_itors attacks()
Gets an iterator over this unit's attacks.
std::map< std::string, std::string > advancement_icons() const
Gets and image path and and associated description for each advancement option.
std::string accuracy_parry_description() const
static std::string flush(std::ostringstream &s)
double get_battery_percentage()
int modified_damage(bool is_backstab) const
Returns the damage per attack of this weapon, considering specials.
const t_translation::ter_list & union_type() const
std::vector< std::string > get_traits_list() const
Gets a list of the traits this unit currently has.
const unit_race * race() const
Gets this unit's race.
static unit_const_ptr get_selected_unit_ptr(reports::context &rc)
const std::string unicode_bullet
static int sort(lua_State *L)
static config unit_defense(reports::context &rc, const unit *u, const map_location &displayed_unit_hex)
config & add_child(config_key_type key)
const t_string & name() const
std::string base_name(const std::string &file, const bool remove_extension)
Returns the base filename of a file, with directory name stripped.
std::map< std::string, reports::generator_function > static_report_generators
bool is_village(const map_location &loc) const
unit_const_ptr get_visible_unit_shared_ptr(const map_location &loc, const team ¤t_team, bool see_all=false) const
const std::string & color() const
const ter_match ALL_OFF_MAP
bool is_fearless() const
Gets whether this unit is fearless - ie, unaffected by time of day.
const std::string weapon_numbers_sep
int experience() const
The current number of experience points this unit has.
UNIT_ALIGNMENT alignment() const
The alignment of this unit.
color_t red_to_green(int val, bool for_text)
Return a color corresponding to the value val red for val=0 to green for val=100, passing by yellow...
const map_location & get_location() const
The current map location this unit is at.
symbol_table string_table
std::size_t viewing_team() const
The viewing team is the team currently viewing the game.
static void add_text(config &report, const std::string &text, const std::string &tooltip, const std::string &help="")
Functions to load and save images from/to disk.
bool can_advance() const
Checks whether this unit has any options to advance to.
const std::string & id() const
std::vector< terrain_code > ter_list
specials_context_t specials_context_for_listing(bool attacking=true) const
static config unit_moves(reports::context &rc, const unit *u, bool is_visible_unit)
t_string unit_description() const
A detailed description of this unit.
static const map_location & null_location()
int total_movement() const
The maximum moves this unit has.
unsigned int num_blows
Effective number of blows, takes swarm into account.
std::string base_str() const
bool fogged(const map_location &loc) const
const t_string & income_description_ally() const
std::string unit_level_tooltip(const int level, const std::vector< std::string > &adv_to_types, const std::vector< config > &adv_to_mods)
int side() const
The side this unit belongs to.
static void reverse(lua_State *L, StkId from, StkId to)
specials_context_t specials_context(unit_const_ptr self, unit_const_ptr other, const map_location &unit_loc, const map_location &other_loc, bool attacking, const_attack_ptr other_attack) const
std::string signed_value(int val)
Convert into a signed value (using the Unicode "−" and +0 convention.
int resistance_against(const std::string &damage_name, bool attacker, const map_location &loc, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr) const
The unit's resistance against a given damage type.
std::vector< std::pair< std::string, std::string > > amla_icons() const
Gets the image and description data for modification advancements.
A config object defines a single node in a WML file, with access to child nodes.
static std::string alignment_description(ALIGNMENT align, unit_race::GENDER gender=unit_race::MALE)
std::shared_ptr< const attack_type > const_attack_ptr
static config unit_vision(const unit *u)
const std::set< map_location > & villages() const
This module contains various pathfinding functions and utilities.
bool file_exists() const
Tests whether the file the locator points at exists.
bool use_twelve_hour_clock_format()
int movement_left() const
Gets how far a unit can move, considering the incapacitated flag.
std::string image_mods() const
Gets an IPF string containing all IPF image mods.
std::vector< map_location > & steps
int max_attacks() const
The maximum number of attacks this unit may perform per turn, usually 1.
const std::string & icon_image() const
static game_display * get_singleton()
const std::vector< t_string > & trait_descriptions() const
Gets the descriptions of the currently registered traits.
int combat_modifier(const unit_map &units, const gamemap &map, const map_location &loc, unit_type::ALIGNMENT alignment, bool is_fearless)
Returns the amount that a unit's damage should be multiplied by due to the current time of day...
const color_t inactive_ability_color