22 #include "formula/callable_objects.hpp"
38 #define ERR_CF LOG_STREAM(err, log_config)
39 #define WRN_CF LOG_STREAM(warn, log_config)
40 #define LOG_CONFIG LOG_STREAM(info, log_config)
41 #define DBG_CF LOG_STREAM(debug, log_config)
44 #define DBG_UT LOG_STREAM(debug, log_unit)
45 #define ERR_UT LOG_STREAM(err, log_unit)
48 #define ERR_WML LOG_STREAM(err, log_wml)
54 other_attack_(nullptr),
55 description_(cfg[
"description"].t_str()),
60 min_range_(cfg[
"min_range"].to_int(1)),
61 max_range_(cfg[
"max_range"].to_int(1)),
62 damage_(cfg[
"damage"]),
63 num_attacks_(cfg[
"number"]),
64 attack_weight_(cfg[
"attack_weight"].to_double(1.0)),
65 defense_weight_(cfg[
"defense_weight"].to_double(1.0)),
66 accuracy_(cfg[
"accuracy"]),
67 movement_used_(cfg[
"movement_used"].to_int(100000)),
68 attacks_used_(cfg[
"attacks_used"].to_int(1)),
70 specials_(cfg.child_or_empty(
"specials")),
80 icon_ =
"attacks/blank-attack.png";
106 const std::vector<std::string>& filter_range =
utils::split(filter[
"range"]);
107 const std::string& filter_damage = filter[
"damage"];
108 const std::string& filter_attacks = filter[
"number"];
109 const std::string& filter_accuracy = filter[
"accuracy"];
110 const std::string& filter_parry = filter[
"parry"];
111 const std::string& filter_movement = filter[
"movement_used"];
112 const std::string& filter_attacks_used = filter[
"attacks_used"];
113 const std::vector<std::string> filter_name =
utils::split(filter[
"name"]);
114 const std::vector<std::string> filter_type =
utils::split(filter[
"type"]);
115 const std::vector<std::string> filter_special =
utils::split(filter[
"special"]);
116 const std::vector<std::string> filter_special_id =
utils::split(filter[
"special_id"]);
117 const std::vector<std::string> filter_special_type =
utils::split(filter[
"special_type"]);
118 const std::vector<std::string> filter_special_active =
utils::split(filter[
"special_active"]);
119 const std::vector<std::string> filter_special_id_active =
utils::split(filter[
"special_id_active"]);
120 const std::vector<std::string> filter_special_type_active =
utils::split(filter[
"special_type_active"]);
121 const std::string filter_formula = filter[
"formula"];
123 if ( !filter_range.empty() && std::find(filter_range.begin(), filter_range.end(), attack.
range()) == filter_range.end() )
144 if ( !filter_name.empty() && std::find(filter_name.begin(), filter_name.end(), attack.
id()) == filter_name.end() )
147 if ( !filter_type.empty() && std::find(filter_type.begin(), filter_type.end(), attack.
type()) == filter_type.end() )
150 if(!filter_special.empty()) {
153 for(
auto& special : filter_special) {
163 if(!filter_special_id.empty()) {
165 for(
auto& special : filter_special_id) {
166 if(attack.
has_special(special,
true,
true,
false)) {
176 if(!filter_special_active.empty()) {
179 for(
auto& special : filter_special_active) {
189 if(!filter_special_id_active.empty()) {
191 for(
auto& special : filter_special_id_active) {
201 if(!filter_special_type.empty()) {
203 for(
auto& special : filter_special_type) {
213 if(!filter_special_type_active.empty()) {
215 for(
auto& special : filter_special_type_active) {
226 if (!filter_formula.empty()) {
234 lg::log_to_chat() <<
"Formula error in weapon filter: " <<
e.type <<
" at " <<
e.filename <<
':' <<
e.line <<
")\n";
235 ERR_WML <<
"Formula error in weapon filter: " <<
e.type <<
" at " <<
e.filename <<
':' <<
e.line <<
")";
257 if ( condition.key ==
"and" )
261 else if ( condition.key ==
"or" )
265 else if ( condition.key ==
"not" )
284 const std::string&
set_name = cfg[
"set_name"];
285 const t_string& set_desc = cfg[
"set_description"];
286 const std::string&
set_type = cfg[
"set_type"];
287 const std::string&
set_range = cfg[
"set_range"];
288 const std::string&
set_icon = cfg[
"set_icon"];
289 const std::string& del_specials = cfg[
"remove_specials"];
291 const std::string& increase_damage = cfg[
"increase_damage"];
292 const std::string&
set_damage = cfg[
"set_damage"];
293 const std::string& increase_attacks = cfg[
"increase_attacks"];
294 const std::string& set_attacks = cfg[
"set_attacks"];
297 const std::string& increase_accuracy = cfg[
"increase_accuracy"];
299 const std::string& increase_parry = cfg[
"increase_parry"];
300 const std::string&
set_parry = cfg[
"set_parry"];
301 const std::string& increase_movement = cfg[
"increase_movement_used"];
302 const std::string& set_movement = cfg[
"set_movement_used"];
303 const std::string& increase_attacks_used = cfg[
"increase_attacks_used"];
312 if(set_desc.
empty() ==
false) {
328 if(del_specials.empty() ==
false) {
329 const std::vector<std::string>& dsl =
utils::split(del_specials);
332 std::vector<std::string>::const_iterator found_id =
333 std::find(dsl.begin(), dsl.end(), vp.cfg[
"id"].str());
334 if (found_id == dsl.end()) {
345 "The mode defaults to 'replace', but should often be 'append' instead. The default may change in a future version, or the attribute may become mandatory.");
348 if(mode !=
"append") {
363 if(increase_damage.empty() ==
false) {
370 if(set_attacks.empty() ==
false) {
378 if(increase_attacks.empty() ==
false) {
386 if(increase_accuracy.empty() ==
false) {
394 if(increase_parry.empty() ==
false) {
398 if(set_movement.empty() ==
false) {
402 if(increase_movement.empty() ==
false) {
410 if(increase_attacks_used.empty() ==
false) {
442 if(description !=
nullptr) {
443 const std::string& increase_damage = cfg[
"increase_damage"];
444 const std::string&
set_damage = cfg[
"set_damage"];
445 const std::string& increase_attacks = cfg[
"increase_attacks"];
446 const std::string& set_attacks = cfg[
"set_attacks"];
447 const std::string& increase_accuracy = cfg[
"increase_accuracy"];
449 const std::string& increase_parry = cfg[
"increase_parry"];
450 const std::string&
set_parry = cfg[
"set_parry"];
451 const std::string& increase_movement = cfg[
"increase_movement_used"];
452 const std::string& set_movement = cfg[
"set_movement_used"];
453 const std::string& increase_attacks_used = cfg[
"increase_attacks_used"];
456 std::vector<t_string> desc;
458 if(!increase_damage.empty()) {
461 "<span color=\"$color\">$number_or_percent</span> damage",
462 "<span color=\"$color\">$number_or_percent</span> damage",
463 std::stoi(increase_damage),
464 {{
"number_or_percent",
utils::print_modifier(increase_damage)}, {
"color", increase_damage[0] ==
'-' ?
"#f00" :
"#0f0"}}));
476 if(!increase_attacks.empty()) {
479 "<span color=\"$color\">$number_or_percent</span> strike",
480 "<span color=\"$color\">$number_or_percent</span> strikes",
481 std::stoi(increase_attacks),
482 {{
"number_or_percent",
utils::print_modifier(increase_attacks)}, {
"color", increase_attacks[0] ==
'-' ?
"#f00" :
"#0f0"}}));
485 if(!set_attacks.empty()) {
490 std::stoi(set_attacks),
491 {{
"number", set_attacks}}));
501 if(!increase_accuracy.empty()) {
504 "<span color=\"$color\">$number_or_percent|%</span> accuracy",
505 {{
"number_or_percent",
utils::print_modifier(increase_accuracy)}, {
"color", increase_accuracy[0] ==
'-' ?
"#f00" :
"#0f0"}}));
515 if(!increase_parry.empty()) {
518 "<span color=\"$color\">$number_or_percent</span> parry",
519 {{
"number_or_percent",
utils::print_modifier(increase_parry)}, {
"color", increase_parry[0] ==
'-' ?
"#f00" :
"#0f0"}}));
522 if(!set_movement.empty()) {
525 "$number movement point",
526 "$number movement points",
527 std::stoi(set_movement),
528 {{
"number", set_movement}}));
531 if(!increase_movement.empty()) {
534 "<span color=\"$color\">$number_or_percent</span> movement point",
535 "<span color=\"$color\">$number_or_percent</span> movement points",
536 std::stoi(increase_movement),
537 {{
"number_or_percent",
utils::print_modifier(increase_movement)}, {
"color", increase_movement[0] ==
'-' ?
"#f00" :
"#0f0"}}));
543 "$number attack used",
544 "$number attacks used",
549 if(!increase_attacks_used.empty()) {
552 "<span color=\"$color\">$number_or_percent</span> attack used",
553 "<span color=\"$color\">$number_or_percent</span> attacks used",
554 std::stoi(increase_attacks_used),
555 {{
"number_or_percent",
utils::print_modifier(increase_attacks_used)}, {
"color", increase_attacks_used[0] ==
'-' ?
"#f00" :
"#0f0"}}));
static lg::log_domain log_unit("unit")
static bool matches_simple_filter(const attack_type &attack, const config &filter)
Returns whether or not *this matches the given filter, ignoring the complexities introduced by [and],...
static lg::log_domain log_wml("wml")
static lg::log_domain log_config("config")
bool has_special(const std::string &special, bool simple_check=false, bool special_id=true, bool special_tags=true) const
Returns whether or not *this has a special with a tag or id equal to special.
const std::string & range() const
void set_attacks_used(int value)
int movement_used() const
void set_accuracy(int value)
const std::string & type() const
std::string accuracy_parry_description() const
bool matches_filter(const config &filter) const
Returns whether or not *this matches the given filter.
bool apply_modification(const config &cfg)
Modifies *this using the specifications in cfg, but only if *this matches cfg viewed as a filter.
void set_specials(config value)
void set_defense_weight(double value)
void set_changed(bool value)
void set_parry(int value)
void set_attack_weight(double value)
void set_damage(int value)
bool describe_modification(const config &cfg, std::string *description)
Trimmed down version of apply_modification(), with no modifications actually made.
const std::string & id() const
void set_icon(const std::string &value)
attack_type(const config &cfg)
void set_type(const std::string &value)
void write(config &cfg) const
void set_range(const std::string &value)
bool has_special_or_ability(const std::string &special, bool special_id=true, bool special_tags=true) const
used for abilities used like weapon and true specials
void set_name(const t_string &value)
A config object defines a single node in a WML file, with access to child nodes.
const_all_children_itors all_children_range() const
In-order iteration over all children.
optional_config_impl< config > optional_child(config_key_type key, int n=0)
Euivalent to mandatory_child, but returns an empty optional if the nth child was not found.
config & add_child(config_key_type key)
bool as_bool() const
Returns a boolean state of the variant value.
std::string deprecated_message(const std::string &elem_name, DEP_LEVEL level, const version_info &version, const std::string &detail)
Interfaces for manipulating version numbers of engine, add-ons, etc.
New lexcical_cast header.
Standard logging facilities (interface).
General math utility functions.
bool in_ranges(const Cmp c, const std::vector< std::pair< Cmp, Cmp >> &ranges)
std::stringstream & log_to_chat()
Use this to show WML errors in the ingame chat.
std::string egettext(char const *msgid)
std::vector< std::pair< int, int > > parse_ranges(const std::string &str)
int apply_modifier(const int number, const std::string &amount, const int minimum)
std::string format_conjunct_list(const t_string &empty, const std::vector< t_string > &elems)
Format a conjunctive list.
std::string signed_percent(int val)
Convert into a percentage (using the Unicode "−" and +0% convention.
std::vector< std::string > split(const config_attribute_value &val)
std::string print_modifier(const std::string &mod)
Add a "+" or replace the "-" par Unicode minus.
static map_location::DIRECTION s