52 #include <boost/intrusive_ptr.hpp>
53 #include <boost/function_output_iterator.hpp>
54 #include <boost/range/begin.hpp>
55 #include <boost/range/end.hpp>
58 #pragma warning (push)
59 #pragma warning (disable: 4510 4610)
61 #include <boost/range/algorithm.hpp>
71 #include <SDL_video.h>
77 #define DBG_UT LOG_STREAM(debug, log_unit)
78 #define LOG_UT LOG_STREAM(info, log_unit)
79 #define WRN_UT LOG_STREAM(warn, log_unit)
80 #define ERR_UT LOG_STREAM(err, log_unit)
83 #define ERR_NG LOG_STREAM(err, log_engine)
86 #define WRN_CF LOG_STREAM(warn, log_config)
87 #define ERR_CONFIG LOG_STREAM(err, log_config)
90 #define LOG_RG LOG_STREAM(info, log_enginerefac)
94 const std::string ModificationTypes[] = {
"advancement",
"advance",
"trait",
"object" };
95 const size_t NumModificationTypes =
sizeof(ModificationTypes)/
96 sizeof(*ModificationTypes);
103 static std::vector<const unit *> units_with_cache;
105 const std::string leader_crown_path =
"misc/leader-crown.png";
106 static std::string internalized_attrs[] = {
"type",
"id",
"name",
107 "gender",
"random_gender",
"variation",
"role",
"ai_special",
108 "side",
"underlying_id",
"overlays",
"facing",
"race",
109 "level",
"recall_cost",
"undead_variation",
"max_attacks",
110 "attacks_left",
"alpha",
"zoc",
"flying",
"cost",
111 "max_hitpoints",
"max_moves",
"vision",
"jamming",
"max_experience",
112 "advances_to",
"hitpoints",
"goto_x",
"goto_y",
"moves",
113 "experience",
"resting",
"unrenamable",
"alignment",
114 "canrecruit",
"extra_recruit",
"x",
"y",
"placement",
115 "parent_type",
"description",
"usage",
"halo",
"ellipse",
116 "random_taits",
"upkeep",
"random_traits",
"generate_name",
117 "profile",
"small_profile",
119 "flag_rgb",
"language_name",
"image",
"image_icon"
122 struct t_internalized_attrs_sorter {
123 t_internalized_attrs_sorter()
127 } internalized_attrs_sorter;
133 const std::string* cur_known = boost::begin(internalized_attrs);
135 while(cur_known != end_known) {
139 int comp = cur->first.compare(*cur_known);
141 WRN_UT <<
"Unknown attribute '" << cur->first <<
"' discarded." << std::endl;
144 else if (comp == 0) {
153 WRN_UT <<
"Unknown attribute '" << cur->first <<
"' discarded." << std::endl;
173 LOG_UT <<
"Adding a reference to a unit: id = " << u->
id() <<
", uid = " << u->
underlying_id() <<
", refcount = " << u->
ref_count() <<
" ptr:" << u << std::endl;
175 LOG_UT <<
"Freshly constructed" << std::endl;
184 LOG_UT <<
"Removing a reference to a unit: id = " << u->
id() <<
", uid = " << u->
underlying_id() <<
", refcount = " << u->
ref_count() <<
" ptr:" << u << std::endl;
198 if (type_id.empty()) {
210 const std::vector<unit_race::GENDER>& genders = type.
genders();
211 assert( genders.size() > 0 );
213 if ( random_gender ==
false || genders.size() == 1 ) {
214 return genders.front();
236 return leader_crown_path;
240 T* copy_or_null(
const boost::scoped_ptr<T>& ptr)
242 return ptr ?
new T(*ptr) : nullptr;
249 , advances_to_(o.advances_to_)
251 , type_name_(o.type_name_)
255 , underlying_id_(o.underlying_id_)
256 , undead_variation_(o.undead_variation_)
257 , variation_(o.variation_)
258 , hit_points_(o.hit_points_)
259 , max_hit_points_(o.max_hit_points_)
260 , experience_(o.experience_)
261 , max_experience_(o.max_experience_)
263 , recall_cost_(o.recall_cost_)
264 , canrecruit_(o.canrecruit_)
265 , recruit_list_(o.recruit_list_)
266 , alignment_(o.alignment_)
267 , flag_rgb_(o.flag_rgb_)
268 , image_mods_(o.image_mods_)
269 , unrenamable_(o.unrenamable_)
274 , movement_(o.movement_)
275 , max_movement_(o.max_movement_)
277 , jamming_(o.jamming_)
278 , movement_type_(o.movement_type_)
279 , hold_position_(o.hold_position_)
280 , end_turn_(o.end_turn_)
281 , resting_(o.resting_)
282 , attacks_left_(o.attacks_left_)
283 , max_attacks_(o.max_attacks_)
285 , known_boolean_states_(o.known_boolean_states_)
286 , variables_(o.variables_)
288 , filter_recall_(o.filter_recall_)
289 , emit_zoc_(o.emit_zoc_)
290 , overlays_(o.overlays_)
292 , attacks_(o.attacks_)
294 , trait_names_(o.trait_names_)
295 , trait_descriptions_(o.trait_descriptions_)
296 , unit_value_(o.unit_value_)
298 , interrupted_move_(o.interrupted_move_)
299 , is_fearless_(o.is_fearless_)
300 , is_healthy_(o.is_healthy_)
301 , modification_descriptions_(o.modification_descriptions_)
303 , getsHit_(o.getsHit_)
305 , hp_bar_scaling_(o.hp_bar_scaling_)
306 , xp_bar_scaling_(o.xp_bar_scaling_)
307 , modifications_(o.modifications_)
308 , abilities_(o.abilities_)
309 , advancements_(o.advancements_)
310 , description_(o.description_)
311 , usage_(copy_or_null(o.usage_))
312 , halo_(copy_or_null(o.halo_))
313 , ellipse_(copy_or_null(o.ellipse_))
314 , random_traits_(o.random_traits_)
315 , generate_name_(o.generate_name_)
317 , profile_(o.profile_)
318 , small_profile_(o.small_profile_)
319 , invisibility_cache_()
331 boost::ptr_vector<config>*
vec_;
336 ,
loc_(cfg[
"x"] - 1, cfg[
"y"] - 1)
338 , type_(&
get_unit_type(cfg[
"parent_type"].blank() ? cfg[
"type"] : cfg[
"parent_type"]))
342 , name_(cfg[
"name"].t_str())
344 , undead_variation_()
345 , variation_(cfg[
"variation"].empty() ? type_->default_variation() : cfg[
"variation"])
352 , canrecruit_(cfg[
"canrecruit"].to_bool())
357 , unrenamable_(false)
367 , hold_position_(false)
373 , known_boolean_states_(known_boolean_state_names_.
size(),false)
383 , trait_descriptions_()
386 , interrupted_move_()
387 , is_fearless_(false)
389 , modification_descriptions_()
393 , hp_bar_scaling_(cfg[
"hp_bar_scaling"].blank() ? type_->
hp_bar_scaling() : cfg[
"hp_bar_scaling"])
394 , xp_bar_scaling_(cfg[
"xp_bar_scaling"].blank() ? type_->
xp_bar_scaling() : cfg[
"xp_bar_scaling"])
402 , random_traits_(true)
403 , generate_name_(true)
405 , invisibility_cache_()
425 const vconfig& filter_recall = vcfg->
child(
"filter_recall");
426 if(!filter_recall.
null())
451 if (
const config &mods = cfg.
child(
"modifications")) {
475 alpha_ = lexical_cast_default<fixed_t>(*v);
511 std::vector<std::string> temp_advances =
utils::split(cfg[
"advances_to"]);
512 if(temp_advances.size() == 1 && temp_advances.front() ==
"null") {
514 }
else if(temp_advances.size() >= 1 && temp_advances.front() !=
"") {
525 if(cfg_range.first != cfg_range.second) {
529 }
while(++cfg_range.first != cfg_range.second);
542 if(cfg_range.first != cfg_range.second) {
544 for(
const config& abilities : cfg_range)
554 if (
const config &status_flags = cfg.
child(
"status"))
557 if (st.second.to_bool()) {
562 if(cfg[
"ai_special"] ==
"guardian") {
572 goto_.
x = cfg[
"goto_x"].to_int() - 1;
573 goto_.
y = cfg[
"goto_y"].to_int() - 1;
585 resting_ = cfg[
"resting"].to_bool();
590 if(!cfg[
"recall_cost"].blank()) {
612 for(std::vector<const unit *>::const_iterator
itor = units_with_cache.begin();
613 itor != units_with_cache.end(); ++
itor) {
614 (*itor)->clear_visibility_cache();
617 units_with_cache.clear();
630 , undead_variation_()
631 , variation_(type_->default_variation())
643 , unrenamable_(false)
645 , gender_(gender !=
unit_race::NUM_GENDERS ?
654 , hold_position_(false)
660 , known_boolean_states_( get_known_boolean_state_names().
size(),false)
670 , trait_descriptions_()
673 , interrupted_move_()
674 , is_fearless_(false)
676 , modification_descriptions_()
687 , random_traits_(true)
688 , generate_name_(true)
690 , invisibility_cache_()
715 std::find(units_with_cache.begin(), units_with_cache.end(),
this);
717 if(itor != units_with_cache.end()) {
718 units_with_cache.erase(itor);
720 }
catch (std::exception &
e) {
721 ERR_UT <<
"Caught exception when destroying unit: " << e.what() << std::endl;
829 LOG_UT <<
"Generating a trait for unit type " <<
type().
log_id() <<
" with musthaveonly " << musthaveonly <<
"\n";
834 std::vector<config> candidate_traits;
840 bool already =
false;
841 for (
const config &mod : current_traits)
843 if (mod[
"id"] == tid) {
848 if (already)
continue;
852 if (avl ==
"musthave")
861 if (!musthaveonly && (!
can_recruit() || avl ==
"any"))
862 candidate_traits.push_back(
t);
865 if (musthaveonly)
return;
869 int nb_traits = std::distance(current_traits.first, current_traits.second);
871 for (; nb_traits < max_traits && !candidate_traits.empty(); ++nb_traits)
875 candidate_traits.erase(candidate_traits.begin() +
num);
885 std::vector<std::string>
res;
924 if(!new_type.
usage().empty()) {
1028 static SDL_Color
hp_color_(
int hitpoints,
int max_hitpoints)
1030 double unit_energy = 0.0;
1031 SDL_Color energy_color = {0,0,0,0};
1033 if(max_hitpoints > 0) {
1034 unit_energy = double(hitpoints)/double(max_hitpoints);
1037 if(1.0 == unit_energy){
1038 energy_color.r = 33;
1039 energy_color.g = 225;
1041 }
else if(unit_energy > 1.0) {
1042 energy_color.r = 100;
1043 energy_color.g = 255;
1044 energy_color.b = 100;
1045 }
else if(unit_energy >= 0.75) {
1046 energy_color.r = 170;
1047 energy_color.g = 255;
1049 }
else if(unit_energy >= 0.5) {
1050 energy_color.r = 255;
1051 energy_color.g = 175;
1053 }
else if(unit_energy >= 0.25) {
1054 energy_color.r = 255;
1055 energy_color.g = 155;
1058 energy_color.r = 255;
1062 return energy_color;
1077 const SDL_Color near_advance_color = {255,255,255,0};
1078 const SDL_Color mid_advance_color = {150,255,255,0};
1079 const SDL_Color far_advance_color = {0,205,205,0};
1080 const SDL_Color normal_color = {0,160,225,0};
1081 const SDL_Color near_amla_color = {225,0,255,0};
1082 const SDL_Color mid_amla_color = {169,30,255,0};
1083 const SDL_Color far_amla_color = {139,0,237,0};
1084 const SDL_Color amla_color = {170,0,255,0};
1089 SDL_Color
color=normal_color;
1092 color=near_advance_color;
1093 }
else if(mid_advance){
1094 color=mid_advance_color;
1095 }
else if(far_advance){
1096 color=far_advance_color;
1100 color=near_amla_color;
1101 }
else if(mid_advance){
1102 color=mid_amla_color;
1103 }
else if(far_advance){
1104 color=far_amla_color;
1123 std::vector<std::string>
result;
1128 result.push_back(adv_type->
type_name());
1130 WRN_UT <<
"unknown unit in advances_to list of type "
1131 <<
type().
log_id() <<
": " << adv_type_id <<
"\n";
1167 if ( goal_dur.empty() )
1169 return !mod_dur.empty() && mod_dur !=
"forever";
1171 return mod_dur == goal_dur;
1183 const unit_type * rebuild_from =
nullptr;
1186 for(
unsigned int i = 0;
i != NumModificationTypes; ++
i) {
1200 else if ( rebuild_from ==
nullptr )
1201 rebuild_from = &
type();
1208 if ( rebuild_from !=
nullptr ) {
1269 std::map<std::string, std::string> all_states;
1271 all_states[
s] =
"yes";
1277 all_states.insert(make_pair(
i->first,
"yes"));
1282 if (all_states.find(
"undrainable") != all_states.end() &&
1283 all_states.find(
"unpoisonable") != all_states.end() &&
1284 all_states.find(
"unplagueable") != all_states.end())
1285 all_states[
"not_living"] =
"yes";
1293 return get_state(known_boolean_state_id);
1296 if (state ==
"not_living") {
1326 std::map<std::string, state_t> known_boolean_state_names_map;
1327 known_boolean_state_names_map.insert(std::make_pair(
"slowed",
STATE_SLOWED));
1328 known_boolean_state_names_map.insert(std::make_pair(
"poisoned",
STATE_POISONED));
1329 known_boolean_state_names_map.insert(std::make_pair(
"petrified",
STATE_PETRIFIED));
1330 known_boolean_state_names_map.insert(std::make_pair(
"uncovered",
STATE_UNCOVERED));
1331 known_boolean_state_names_map.insert(std::make_pair(
"not_moved",
STATE_NOT_MOVED));
1332 known_boolean_state_names_map.insert(std::make_pair(
"unhealable",
STATE_UNHEALABLE));
1333 known_boolean_state_names_map.insert(std::make_pair(
"guardian",
STATE_GUARDIAN));
1334 return known_boolean_state_names_map;
1341 set_state(known_boolean_state_id, value);
1345 if (state ==
"not_living") {
1360 if (ab.cfg[
"id"] == ability) {
1371 if (i->cfg[
"id"] == ability) {
1388 cfg[
"halo"] = *
halo_;
1408 cfg[
"side"] =
side_;
1421 cfg[
"role"] =
role_;
1424 std::map<std::string,std::string> all_states =
get_states();
1425 for(std::map<std::string,std::string>::const_iterator st = all_states.begin(); st != all_states.end(); ++st) {
1426 status_flags[st->first] = st->second;
1440 cfg[
"name"] =
name_;
1444 cfg[
"canrecruit"] =
true;
1450 cfg[
"goto_x"] =
goto_.
x + 1;
1451 cfg[
"goto_y"] =
goto_.
y + 1;
1469 cfg[
"alpha"] = std::to_string(
alpha_);
1475 for(std::vector<attack_type>::const_iterator
i =
attacks_.begin();
i !=
attacks_.end(); ++
i) {
1486 cfg.
add_child(
"advancement", advancement);
1504 else if(boost::get<upkeep_full>(&
upkeep_) !=
nullptr) {
1507 else if(boost::get<upkeep_loyal>(&
upkeep_) !=
nullptr) {
1511 return boost::get<int>(
upkeep_);
1517 return boost::get<upkeep_loyal>(&
upkeep_) !=
nullptr;
1527 if (!defense_abilities.
empty()) {
1537 if(!(cfg[
"active_on"].empty() || (attacker && cfg[
"active_on"]==
"offense") || (!attacker && cfg[
"active_on"]==
"defense"))) {
1541 if(!apply_to.empty()) {
1542 if(damage_name != apply_to) {
1543 if ( apply_to.find(
',') != std::string::npos &&
1544 apply_to.find(damage_name) != std::string::npos ) {
1545 const std::vector<std::string>& vals =
utils::split(apply_to);
1546 if(
std::find(vals.begin(),vals.end(),damage_name) == vals.end()) {
1566 i = resistance_abilities.
erase(
i);
1571 if(!resistance_abilities.
empty()) {
1575 resistance_abilities.
highest(
"max_value").first);
1582 std::map<std::string,std::string> temp;
1588 std::ostringstream tooltip;
1593 tooltip <<
s <<
'\n';
1595 temp[
image] = tooltip.str();
1601 if (image.empty())
continue;
1602 std::ostringstream tooltip;
1603 tooltip << temp[
image];
1606 tooltip << tt <<
'\n';
1607 temp[
image] = tooltip.str();
1613 std::vector<std::pair<std::string,std::string> > temp;
1614 std::pair<std::string,std::string> icon;
1618 icon.first = adv[
"icon"].str();
1619 icon.second = adv[
"description"].str();
1624 temp.push_back(icon);
1632 std::vector<config>
res;
1635 if (adv[
"strict_amla"].to_bool() && !
advances_to_.empty())
1637 if (
modification_count(
"advancement", adv[
"id"]) >= unsigned(adv[
"max_times"].to_int(1)))
1640 std::vector<std::string> temp_require =
utils::split(adv[
"require_amla"]);
1641 std::vector<std::string> temp_exclude =
utils::split(adv[
"exclude_amla"]);
1642 if (temp_require.empty() && temp_exclude.empty()) {
1647 std::sort(temp_require.begin(), temp_require.end());
1648 std::sort(temp_exclude.begin(), temp_exclude.end());
1649 std::vector<std::string> uniq_require, uniq_exclude;
1650 std::unique_copy(temp_require.begin(), temp_require.end(), std::back_inserter(uniq_require));
1651 std::unique_copy(temp_exclude.begin(), temp_exclude.end(), std::back_inserter(uniq_exclude));
1653 bool exclusion_found =
false;
1656 int max_num =
std::count(temp_exclude.begin(), temp_exclude.end(),
s);
1658 if (mod_num >= max_num) {
1659 exclusion_found =
true;
1663 if (exclusion_found) {
1667 bool requirements_done =
true;
1670 int required_num =
std::count(temp_require.begin(), temp_require.end(),
s);
1672 if (required_num > mod_num) {
1673 requirements_done =
false;
1677 if (requirements_done) {
1688 for (
config& advancement : advancements)
1699 if (item[
"id"] ==
id) {
1705 if (mod_type ==
"advancement") {
1713 "alignment",
"attack",
"defense",
"ellipse",
"experience",
"fearless",
1714 "halo",
"healthy",
"hitpoints",
"image_mod",
"jamming",
"jamming_costs",
1715 "loyal",
"max_attacks",
"max_experience",
"movement",
"movement_costs",
1716 "new_ability",
"new_advancement",
"new_animation",
"new_attack",
"overlay",
"profile",
1717 "recall_cost",
"remove_ability",
"remove_advancement",
"remove_attacks",
"resistance",
1718 "status",
"type",
"variation",
"vision",
"vision_costs",
"zoc"};
1722 if(apply_to ==
"attack") {
1724 bool first_attack =
true;
1729 bool affected =
a->describe_modification(effect, &desc);
1730 if(affected && desc !=
"") {
1732 first_attack =
false;
1734 attack_names +=
t_string(
N_(
" and "),
"wesnoth");
1737 attack_names +=
t_string(
a->name(),
"wesnoth-units");
1740 if (!attack_names.empty()) {
1742 symbols[
"attack_list"] = attack_names;
1743 symbols[
"effect_description"] = desc;
1744 return vgettext(
"$attack_list|: $effect_description", symbols);
1746 }
else if(apply_to ==
"hitpoints") {
1747 const std::string &increase_total = effect[
"increase_total"];
1749 if(!increase_total.empty()) {
1753 }
else if(apply_to ==
"movement") {
1756 if(!increase.empty()) {
1759 _n(
"move",
"moves", n);
1761 }
else if(apply_to ==
"vision") {
1764 if(!increase.empty()) {
1767 }
else if(apply_to ==
"jamming") {
1770 if(!increase.empty()) {
1773 }
else if(apply_to ==
"max_experience") {
1776 if(!increase.empty()) {
1780 }
else if (apply_to ==
"max_attacks") {
1784 const char*
const singular =
N_(
"attack per turn");
1785 const char*
const plural =
N_(
"attacks per turn");
1786 if (increase[increase.size()-1] ==
'%' || abs(lexical_cast<int>(increase)) != 1) {
1787 description +=
t_string(plural,
"wesnoth");
1789 description +=
t_string(singular,
"wesnoth");
1792 }
else if (apply_to ==
"recall_cost") {
1802 if(apply_to ==
"fearless")
1806 else if(apply_to ==
"healthy")
1810 else if(apply_to ==
"profile") {
1822 }
else if(apply_to ==
"new_attack") {
1824 }
else if(apply_to ==
"remove_attacks") {
1827 if(a->matches_filter(effect)) {
1833 }
else if(apply_to ==
"attack") {
1836 a->apply_modification(effect);
1838 }
else if(apply_to ==
"hitpoints") {
1840 const std::string &increase_hp = effect[
"increase"];
1841 const std::string &increase_total = effect[
"increase_total"];
1843 const std::string &set_total = effect[
"set_total"];
1846 const bool violate_max = effect[
"violate_maximum"].to_bool();
1848 if(!set_hp.empty()) {
1849 if(set_hp[set_hp.size()-1] ==
'%') {
1850 hit_points_ = lexical_cast_default<int>(set_hp)*max_hit_points_/100;
1855 if(!set_total.empty()) {
1856 if(set_total[set_total.size()-1] ==
'%') {
1857 max_hit_points_ = lexical_cast_default<int>(set_total)*max_hit_points_/100;
1859 max_hit_points_ = lexical_cast_default<int>(set_total);
1863 if(!increase_total.empty()) {
1868 if(max_hit_points_ < 1)
1869 max_hit_points_ = 1;
1871 if (effect[
"heal_full"].to_bool()) {
1875 if(!increase_hp.empty()) {
1880 if(
hit_points_ > max_hit_points_ && !violate_max) {
1881 LOG_UT <<
"resetting hp to max\n";
1887 }
else if(apply_to ==
"movement") {
1890 if(!increase.empty()) {
1898 }
else if(apply_to ==
"vision") {
1901 if(!increase.empty()) {
1907 }
else if(apply_to ==
"jamming") {
1910 if(!increase.empty()) {
1915 }
else if(apply_to ==
"experience") {
1920 if(set[set.size()-1] ==
'%') {
1927 if(increase.empty() ==
false) {
1930 }
else if(apply_to ==
"max_experience") {
1934 if(set.empty() ==
false) {
1935 if(set[set.size()-1] ==
'%') {
1942 if(increase.empty() ==
false) {
1945 }
else if(apply_to ==
"loyal") {
1947 }
else if(apply_to ==
"status") {
1962 }
else if (apply_to ==
"movement_costs") {
1963 if (
const config &ap = effect.
child(
"movement_costs")) {
1966 }
else if (apply_to ==
"vision_costs") {
1967 if (
const config &ap = effect.
child(
"vision_costs")) {
1970 }
else if (apply_to ==
"jamming_costs") {
1971 if (
const config &ap = effect.
child(
"jamming_costs")) {
1974 }
else if (apply_to ==
"defense") {
1978 }
else if (apply_to ==
"resistance") {
1979 if (
const config &ap = effect.
child(
"resistance")) {
1982 }
else if (apply_to ==
"zoc") {
1986 }
else if (apply_to ==
"new_ability") {
1987 if (
const config &ab_effect = effect.
child(
"abilities")) {
1996 }
else if (apply_to ==
"remove_ability") {
1997 if (
const config &ab_effect = effect.
child(
"abilities")) {
2002 }
else if (apply_to ==
"image_mod") {
2003 LOG_UT <<
"applying image_mod \n";
2008 LOG_UT <<
"applying image_mod \n";
2009 mod = effect[
"add"].str();
2019 LOG_UT <<
"applying image_mod \n";
2020 }
else if (apply_to ==
"new_animation") {
2021 anim_comp_->apply_new_animation_effect(effect);
2022 }
else if (apply_to ==
"ellipse") {
2024 }
else if (apply_to ==
"halo") {
2026 }
else if (apply_to ==
"overlay") {
2033 for (it=temp_overlays.begin();it<temp_overlays.end();++it) {
2037 else if (!replace.empty()) {
2040 }
else if (apply_to ==
"new_advancement") {
2042 const bool replace = effect[
"replace"].to_bool(
false);
2044 if (!types.empty()) {
2049 std::copy(temp_advances.begin(), temp_advances.end(), std::back_inserter(
advances_to_));
2060 }
else if (apply_to ==
"remove_advancement") {
2074 std::vector<size_t> remove_indices;
2081 }
else if (apply_to ==
"alignment") {
2082 unit_type::ALIGNMENT new_align;
2083 if(new_align.parse(effect[
"set"])) {
2086 }
else if (apply_to ==
"max_attacks") {
2089 if(!increase.empty()) {
2092 }
else if (apply_to ==
"recall_cost") {
2098 if(set[set.size()-1] ==
'%') {
2105 if(!increase.empty()) {
2108 }
else if (effect[
"apply_to"] ==
"variation") {
2111 assert(base_type !=
nullptr);
2113 }
else if (effect[
"apply_to"] ==
"type") {
2115 if (prev_type.empty()) {
2121 const bool heal_full = effect[
"heal_full"].to_bool(
false);
2128 WRN_UT <<
"unknown type= in [effect]apply_to=type, ignoring" << std::endl;
2135 bool generate_description = mod[
"generate_description"].to_bool(
true);
2137 if(no_add ==
false) {
2140 bool set_poisoned =
false;
2142 std::vector<t_string> effects_description;
2146 if (
const config &afilter = effect.
child(
"filter")) {
2151 int times = effect[
"times"].to_int(1);
2154 if (effect[
"times"] ==
"per level")
2162 if (apply_to ==
"variation" || apply_to ==
"type") {
2164 set_poisoned =
false;
2165 last_effect = effect;
2179 description += description_component;
2182 set_poisoned =
true;
2184 set_poisoned =
false;
2195 if (effect[
"times"] ==
"per level" && !times) {
2197 symbols[
"effect_description"] = description;
2198 description =
vgettext(
"$effect_description per level", symbols);
2200 if(!description.
empty())
2201 effects_description.push_back(description);
2205 if (!last_effect.
empty() && no_add ==
false) {
2213 effects_description.push_back(description);
2222 const t_string& mod_description = mod[
"description"];
2223 if (!mod_description.
empty()) {
2224 description = mod_description +
" ";
2229 if(effects_description.empty() ==
false && generate_description ==
true) {
2230 for(std::vector<t_string>::const_iterator
i = effects_description.begin();
2231 i != effects_description.end(); ++
i) {
2236 if(
i+1 != effects_description.end())
2237 description +=
t_string(
N_(
" and "),
"wesnoth");
2242 if ( mod_type ==
"trait" ) {
2254 const t_string name = gender_specific_name.
empty() ? trait[
"name"] : gender_specific_name;
2275 for(
size_t i = 0;
i != NumModificationTypes; ++
i) {
2278 lg::wml_error() <<
"[modifications][advance] is deprecated, use [advancement] instead\n";
2294 DBG_UT <<
"unit::invisible called: id = " <<
id() <<
" loc = " << loc <<
" get_loc = " <<
get_location() << std::endl;
2310 return itor->second;
2324 units_with_cache.push_back(
this);
2362 std::stringstream ss;
2379 std::string::size_type
pos =
id_.find_last_of(
'-');
2380 if(pos != std::string::npos && pos+1 <
id_.size()
2381 &&
id_.find_first_not_of(
"0123456789", pos+1) == std::string::npos) {
2383 WRN_UT <<
"assigning new id to clone of generic unit " <<
id_ << std::endl;
2393 u_(u), moves_(u.movement_left(true))
2410 DBG_UT <<
"The unit to be removed is not in the unit map.\n";
2419 return id_ == unit_id;
2424 std::stringstream modifier;
2428 return modifier.str();
2431 std::stringstream modifier;
2436 return modifier.str();
2477 if (upkeep.
empty()) {
2481 int upkeep_int = upkeep.
to_int(-99);
2482 if(upkeep_int != -99) {
2485 else if(upkeep ==
"loyal" || upkeep ==
"free") {
2488 else if(upkeep ==
"full") {
2492 WRN_UT <<
"Fund invalid upkeep=\"" << upkeep <<
"\" in a unit\n";
2498 if(boost::get<upkeep_full>(&
upkeep_) !=
nullptr) {
2501 else if(boost::get<upkeep_loyal>(&
upkeep_) !=
nullptr) {
2505 upkeep = boost::get<int>(
upkeep_);
2514 u.
write(unit_config);
2522 "ignore_race_traits",
2523 "ignore_global_traits",
2540 for (
int i = 0; !main_keys[
i].empty(); ++
i)
2542 wcfg[main_keys[
i]] = unit_config[main_keys[
i]];
2555 for (
int i = 0; !attack_keys[
i].empty(); ++
i) {
2556 child[attack_keys[
i]] = att[attack_keys[
i]];
2583 const std::string child_keys[] = {
"advance_from",
"defense",
"movement_costs",
"vision_costs",
"jamming_costs",
"resistance",
""};
2585 for (
int i = 0; !child_keys[
i].empty(); ++
i)
std::string image_mods() const
static unit_id create_real(size_t val)
child_itors child_range(const std::string &key)
static const std::set< std::string > builtin_effects
int total_movement() const
void generate_traits(bool musthaveonly=false)
Apply mandatory traits (e.g.
const std::string & id() const
t_string unit_description() const
Information about the unit – a detailed description of it.
bool is_visible_to_team(team const &team, gamemap const &map, bool const see_all=true) const
t_string type_name_
Never nullptr. Adjusted for gender and variation.
std::string apply_effect(const std::string &name, unit &u, const config &cfg, bool need_apply)
static DIRECTION parse_direction(const std::string &str)
std::vector< bool > known_boolean_states_
void apply_builtin_effect(std::string type, const config &effect)
const map_location & get_location() const
std::vector< std::string > recruit_list_
std::string const & gender_string(unit_race::GENDER gender)
static int get_acceleration()
void set_usage(const std::string &usage)
resistances & get_resistances()
void set_hidden(bool state) const
std::string absolute_image() const
The name of the file to game_display (used in menus).
const std::string log_id() const
A variant on id() that is more descriptive, for use with message logging.
ptr_vector_pushback(boost::ptr_vector< config > &vec)
utils::string_map modification_descriptions_
all_children_iterator ordered_end() const
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
unit_movement_resetter(unit &u, bool operate=true)
const unit_type & get_gender_unit_type(std::string gender) const
std::pair< const_attribute_iterator, const_attribute_iterator > const_attr_itors
int max_hitpoints() const
const t_string & type_name() const
The name of the unit in the current language setting.
bool get_state(const std::string &state) const
void parse_upkeep(const config::attribute_value &upkeep)
size_t underlying_id() const
The unique internal ID of the unit.
void intrusive_ptr_release(const unit *u)
std::string TC_image_mods() const
void append(const config &cfg)
Append data from another config object to this one.
std::vector< std::string > advances_to_
unit_id next_id()
returns id for unit that is created
iterator erase(const iterator &erase_it)
std::vector< config > get_modification_advances() const
~unit_movement_resetter()
std::vector< t_string > trait_names_
void remove_movement_ai()
vconfig child(const std::string &key) const
Returns a child of *this whose key is key.
rng * generator
This generator is automatically synced during synced context.
GLuint GLuint GLsizei GLenum type
static l_noret error(LoadState *S, const char *why)
bool matches_id(const std::string &unit_id) const
void set_image_halo(const std::string &halo)
unit & operator=(unit)
Assignment operator.
unit_type::ALIGNMENT alignment_
const movetype & movement_type() const
void intrusive_ptr_add_ref(const unit *u)
Intrusive Pointer interface.
bool is_enemy(int n) const
map_location::DIRECTION facing_
double xp_bar_scaling() const
attribute_map::value_type attribute
const std::vector< std::string > advances_to_translated() const
void set_image_ellipse(const std::string &ellipse)
const std::string & undead_variation() const
Info on the type of unit that the unit reanimates as.
GLenum GLsizei GLenum GLenum const GLvoid * image
const std::string & id() const
bool resistance_filter_matches(const config &cfg, bool attacker, const std::string &damage_name, int res) const
void advance_to(const unit_type &t, bool use_traits=false)
Advances this unit to another type.
unit_type_data unit_types
const unit_race * race() const
Never returns nullptr, but may point to the null race.
const std::string & image() const
void merge(const config &new_data, bool overwrite)
Merges the given config over the existing costs.
void write(config &cfg) const
Writes the movement type data to the provided config.
const config & abilities_cfg() const
std::pair< int, map_location > highest(const std::string &key, int def=0) const
void write(config &cfg) const
SDL_Color xp_color() const
Colors for the unit's XP.
void write_upkeep(config::attribute_value &upkeep) const
void set_state(const std::string &state, bool value)
const config & child_or_empty(const std::string &key) const
Returns the first child with the given key, or an empty config if there is none.
bool generate_name() const
void merge(const config &new_cfg, bool overwrite=true)
Merges the given config over the existing data.
bool get_ability_bool(const std::string &tag_name, const map_location &loc) const
Returns true if the unit is currently under effect by an ability with this given TAG NAME...
void clear_children(const std::string &key)
To lexical_cast(From value)
Lexical cast converts one type to another.
bool empty() const
Tests for an attribute that either was never set or was set to "".
void expire_modifications(const std::string &duration)
Clears those modifications whose duration has expired.
std::string ellipse() const
std::string small_profile() const
The unit's profile.
GLsizei GLenum GLenum * types
void operator()(const config &cfg)
std::pair< const_child_iterator, const_child_iterator > const_child_itors
Variant for storing WML attributes.
int defense_modifier(const t_translation::t_terrain &terrain) const
std::string small_profile_
static std::map< std::string, state_t > known_boolean_state_names_
bool filter_base_matches(const config &cfg, int def)
std::string describe_builtin_effect(std::string type, const config &effect)
std::vector< unit_ability >::iterator iterator
terrain_costs & get_jamming()
const std::vector< std::string > & recruits() const
t_advancements advancements_
void apply_modifications()
const unit_type & type() const
The type of the unit (accounting for gender and variation).
int get_random_int(int min, int max)
This helper method provides a random int from the underlying generator, using results of next_random...
std::map< std::string, std::string > advancement_icons() const
bool has_child(const std::string &key) const
Determine whether a config has a child or not.
const std::string & type_id() const
The id of the type of the unit.
static void clear_status_caches()
Clear the unit status cache for all units.
This class stores all the data for a single 'side' (in game nomenclature).
A small explanation about what's going on here: Each action has access to two game_info objects First...
static const std::string & leader_crown()
The path to the leader crown overlay.
static lg::log_domain log_enginerefac("enginerefac")
void set_facing(map_location::DIRECTION dir) const
const unit_race * find_race(const std::string &) const
const std::string & flag_rgb() const
std::map< std::string, t_string > string_map
void swap(unit &)
Swap, for copy and swap idiom.
std::vector< team > * teams
static const unit_race null_race
Dummy race used when a race is not yet known.
child_list get_children(const std::string &key) const
const std::string & big_profile() const
bool matches(const unit &u, const map_location &loc) const
Determine if *this matches filter at a specified location.
filter_context * filter_con
void add_color_info(const config &v)
GLsizei const GLfloat * value
all_children_itors all_children_range() const
In-order iteration over all children.
terrain_defense & get_defense()
terrain_costs & get_vision()
void set_recruits(const std::vector< std::string > &recruits)
GLboolean GLboolean GLboolean GLboolean a
void add_trait_description(const config &trait, const t_string &description)
register a trait's name and its description for UI's use
Encapsulates the map of the game.
void remove_child(const std::string &key, unsigned index)
static UNUSEDNOWARN std::string _n(const char *str1, const char *str2, int n)
const std::vector< unit_race::GENDER > & genders() const
The returned vector will not be empty, provided this has been built to the HELP_INDEXED status...
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
config & add_child(const std::string &key)
const t_advancements & modification_advancements() const
const std::string & icon() const
bool mod_duration_match(const std::string &mod_dur, const std::string &goal_dur)
Determines if mod_dur "matches" goal_dur.
unit_race::GENDER gender_
boost::scoped_ptr< unit_animation_component > anim_comp_
int movement_left() const
Returns how far a unit can move this turn (zero if incapacitated).
static const ::config * terrain
The terrain used to create the cache.
void merge(const config &new_data, bool overwrite)
Merges the given config over the existing costs.
boost::scoped_ptr< std::string > halo_
const std::string & small_profile() const
void check_types(const std::vector< std::string > &types) const
game_events::manager * game_events
terrain_costs & get_movement()
GLuint GLuint GLsizei count
all_children_iterator erase(const all_children_iterator &i)
bool invisible(const map_location &loc, bool see_all=true) const
const std::string ¶meters float amount
A terrain string which is converted to a terrain is a string with 1 or 2 layers the layers are separa...
std::string join(T const &v, const std::string &s=",")
Generates a new string joining container items in a list.
boost::scoped_ptr< std::string > usage_
std::vector< std::string > overlays_
Encapsulates the map of the game.
static lg::log_domain log_config("config")
config::const_child_itors advancements() const
std::vector< std::pair< std::string, std::string > > amla_icons() const
std::string default_anim_image() const
The default image to use for animation frames with no defined image.
const std::string & usage() const
const std::vector< std::string > & advances_to() const
void add_modification(const std::string &type, const config &modification, bool no_add=false)
double hp_bar_scaling() const
const std::vector< std::string > & advances_to() const
unit & clone(bool is_temporary=true)
Mark this unit as clone so it can be inserted to unit_map.
std::map< std::string, tfilter >::iterator itor
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
int resistance_against(const attack_type &attack) const
Returns the resistance against the indicated attack.
std::string get_checksum(const unit &u)
Gets a checksum for a unit.
const unit_type & get_variation(const std::string &id) const
const std::map< std::string, std::string > get_states() const
size_t modification_count(const std::string &type, const std::string &id) const
config::const_child_itors possible_traits() const
const config & get_config() const
const_attr_itors attribute_range() const
map_location interrupted_move_
boost::scoped_ptr< unit_formula_manager > formula_man_
void set_interrupted_move(const map_location &interrupted_move)
#define log_scope(description)
void set_movement(int moves, bool unit_action=false)
Set the unit's remaining movement to moves.
n_unit::unit_id underlying_id_
DIRECTION
Valid directions which can be moved in our hexagonal world.
bool fogged(const map_location &loc) const
std::string generate_name(GENDER gender) const
void validate_side(int side)
std::set< std::string > & encountered_units()
GLdouble GLdouble GLdouble r
static int sort(lua_State *L)
unit_ability_list get_abilities(const std::string &tag_name, const map_location &loc) const
unsigned child_count(const std::string &key) const
int resistance_against(const std::string &damage_name, bool attacker, const map_location &loc) const
std::string big_profile() const
Handling of system events.
std::string replace(std::string str, const std::string &src, const std::string &dst)
Replace all instances of src in str with dst.
GLuint const GLchar * name
const attribute_value * get(const std::string &key) const
Returns a pointer to the attribute with the given key or nullptr if it does not exist.
int experience_needed(bool with_acceleration=true) const
bool on_board(const map_location &loc) const
Tell if a location is on the map.
config::const_child_itors events() const
static const unit_type & get_unit_type(const std::string &type_id)
Converts a string ID to a unit_type.
const std::string & effect_image_mods() const
const std::string & base_id() const
The id of the original type from which this (variation) descended.
std::vector< std::string > parenthetical_split(std::string const &val, const char separator, std::string const &left, std::string const &right, const int flags)
Splits a string based either on a separator where text within parenthesis is protected from splitting...
static unit_race::GENDER generate_gender(const unit_type &type, bool random_gender)
void set_advancements(std::vector< config > advancements)
n_unit::id_manager & unit_id_manager()
int max_experience() const
static state_t get_known_boolean_state_id(const std::string &state)
SDL_Color hp_color() const
Colors for the unit's current hitpoints.
boost::scoped_ptr< std::string > ellipse_
bool find(E event, F functor)
Tests whether an event handler is available.
int apply_modifier(const int number, const std::string &amount, const int minimum)
std::vector< attack_type > attacks_
void swap(game_board &one, game_board &other)
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
std::vector< attack_type > attacks() const
A variable-expanding proxy for the config class.
this module manages the cache of images.
void adjust_profile(std::string &profile)
Standard logging facilities (interface).
const unit_race * race_
The displayed name of the unit type.
static void check_id(std::string &id)
game_lua_kernel * lua_kernel
void recursive_clear_value(const std::string &key)
std::map< map_location, bool > invisibility_cache_
Hold the visibility status cache for a unit, when not uncovered.
void set_attacks(int left)
static std::map< std::string, state_t > get_known_boolean_state_names()
int to_int(int def=0) const
static std::string get_side_color_index(int side)
unsigned int num_traits() const
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
std::string id_
Never nullptr, but may point to the null race.
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
static SDL_Color hp_color_(int hitpoints, int max_hitpoints)
std::vector< t_string > trait_descriptions_
boost::ptr_vector< config > * vec_
int get_composite_value() const
std::vector< vconfig > child_list
bool has_ability_by_id(const std::string &ability) const
A config object defines a single node in a WML file, with access to child nodes.
void remove_ability_by_id(const std::string &ability)
static lg::log_domain log_engine("engine")
std::string print_modifier(const std::string &mod)
void set_underlying_id(n_unit::id_manager &id_manager)
static std::string write_direction(DIRECTION dir)
bool would_be_discovered(const map_location &loc, int side_num, bool see_all=true)
Given a location and a side number, indicates whether an invisible unit of that side at that location...
Defines the MAKE_ENUM macro.
void add_events(const config::const_child_itors &cfgs, const std::string &type=std::string())
GLsizei const GLcharARB ** string
static lg::log_domain log_unit("unit")
void merge(const config &new_values, bool overwrite)
Merges the given config over the existing values.
const std::string & id() const
The id for this unit_type.
int defense_modifier(const t_translation::t_terrain &terrain) const
Returns the defensive value of the indicated terrain.
std::set< std::string > states_
void set_advances_to(const std::vector< std::string > &advances_to)
t_string unit_description() const
const config & get_cfg_for_units() const
Returns a trimmed config suitable for use with units.
all_children_iterator ordered_begin() const
std::string undead_variation_
std::vector< std::string > get_traits_list() const