move filter_abilitie/specials code in abilities.cpp
The code was moved to abilities.cpp so that it can be called from the units or attack_type functions, the attack_type function state necessary for the tags [filter_special_active] and [remove_specials] which I plan to implement when the code for filter_ability] is validated in its final form.
This commit is contained in:
parent
788cedc99a
commit
24859f861a
3 changed files with 151 additions and 130 deletions
|
@ -35,6 +35,7 @@
|
|||
#include "units/abilities.hpp"
|
||||
#include "units/filter.hpp"
|
||||
#include "units/map.hpp"
|
||||
#include "utils/config_filters.hpp"
|
||||
#include "filter_context.hpp"
|
||||
#include "formula/callable_objects.hpp"
|
||||
#include "formula/formula.hpp"
|
||||
|
@ -1524,9 +1525,7 @@ bool attack_type::overwrite_special_checking(unit_ability_list& overwriters, con
|
|||
if(overwrite_specials){
|
||||
auto overwrite_filter = (*overwrite_specials).optional_child("experimental_filter_specials");
|
||||
if(overwrite_filter && is_overwritable && one_side_overwritable){
|
||||
if(self_){
|
||||
special_matches = (*self_).ability_matches_filter(cfg, tag_name, *overwrite_filter);
|
||||
}
|
||||
special_matches = special_matches_filter(cfg, tag_name, *overwrite_filter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1743,6 +1742,146 @@ bool attack_type::has_special_or_ability(const std::string& special, bool specia
|
|||
}
|
||||
//end of emulate weapon special functions.
|
||||
|
||||
namespace
|
||||
{
|
||||
bool matches_ability_filter(const config & cfg, const std::string& tag_name, const config & filter)
|
||||
{
|
||||
using namespace utils::config_filters;
|
||||
|
||||
if(!filter["affect_adjacent"].empty()){
|
||||
bool adjacent = cfg.has_child("affect_adjacent");
|
||||
if(filter["affect_adjacent"].to_bool() != adjacent){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!bool_matches_if_present(filter, cfg, "affect_self", true))
|
||||
return false;
|
||||
|
||||
if(!bool_or_empty(filter, cfg, "affect_allies"))
|
||||
return false;
|
||||
|
||||
if(!bool_matches_if_present(filter, cfg, "affect_enemies", false))
|
||||
return false;
|
||||
|
||||
if(!bool_matches_if_present(filter, cfg, "cumulative", false))
|
||||
return false;
|
||||
|
||||
const std::vector<std::string> filter_type = utils::split(filter["tag_name"]);
|
||||
if ( !filter_type.empty() && std::find(filter_type.begin(), filter_type.end(), tag_name) == filter_type.end() )
|
||||
return false;
|
||||
|
||||
if(!string_matches_if_present(filter, cfg, "id", ""))
|
||||
return false;
|
||||
|
||||
if(tag_name == "resistance"){
|
||||
if(!set_includes_if_present(filter, cfg, "apply_to")){
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!string_matches_if_present(filter, cfg, "apply_to", "self")){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!string_matches_if_present(filter, cfg, "overwrite_specials", "none"))
|
||||
return false;
|
||||
|
||||
if(!string_matches_if_present(filter, cfg, "active_on", "both"))
|
||||
return false;
|
||||
|
||||
//for damage only
|
||||
if(!string_matches_if_present(filter, cfg, "replacement_type", ""))
|
||||
return false;
|
||||
|
||||
if(!string_matches_if_present(filter, cfg, "alternative_type", ""))
|
||||
return false;
|
||||
|
||||
//for plague only
|
||||
if(!string_matches_if_present(filter, cfg, "type", ""))
|
||||
return false;
|
||||
|
||||
if(!filter["value"].empty()){
|
||||
if(tag_name == "drains"){
|
||||
if(!int_matches_if_present(filter, cfg, "value", 50)){
|
||||
return false;
|
||||
}
|
||||
} else if(tag_name == "berserk"){
|
||||
if(!int_matches_if_present(filter, cfg, "value", 1)){
|
||||
return false;
|
||||
}
|
||||
} else if(tag_name == "heal_on_hit" || tag_name == "heals" || tag_name == "regenerate" || tag_name == "leadership"){
|
||||
if(!int_matches_if_present(filter, cfg, "value" , 0)){
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!int_matches_if_present(filter, cfg, "value")){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!int_matches_if_present_or_negative(filter, cfg, "add", "sub"))
|
||||
return false;
|
||||
|
||||
if(!int_matches_if_present_or_negative(filter, cfg, "sub", "add"))
|
||||
return false;
|
||||
|
||||
if(!double_matches_if_present(filter, cfg, "multiply"))
|
||||
return false;
|
||||
|
||||
if(!double_matches_if_present(filter, cfg, "divide"))
|
||||
return false;
|
||||
|
||||
//the wml_filter is used in cases where the attribute we are looking for is not
|
||||
//previously listed or to check the contents of the sub_tags ([filter_adjacent],[filter_self],[filter_opponent] etc.
|
||||
//If the checked set does not exactly match the content of the capability, the function returns a false response.
|
||||
auto fwml = filter.optional_child("filter_wml");
|
||||
if (fwml){
|
||||
if(!cfg.matches(*fwml)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Passed all tests.
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool common_matches_filter(const config & cfg, const std::string& tag_name, const config & filter)
|
||||
{
|
||||
// Handle the basic filter.
|
||||
bool matches = matches_ability_filter(cfg, tag_name, filter);
|
||||
|
||||
// Handle [and], [or], and [not] with in-order precedence
|
||||
for (const config::any_child condition : filter.all_children_range() )
|
||||
{
|
||||
// Handle [and]
|
||||
if ( condition.key == "and" )
|
||||
matches = matches && common_matches_filter(cfg, tag_name, condition.cfg);
|
||||
|
||||
// Handle [or]
|
||||
else if ( condition.key == "or" )
|
||||
matches = matches || common_matches_filter(cfg, tag_name, condition.cfg);
|
||||
|
||||
// Handle [not]
|
||||
else if ( condition.key == "not" )
|
||||
matches = matches && !common_matches_filter(cfg, tag_name, condition.cfg);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
}
|
||||
|
||||
bool unit::ability_matches_filter(const config & cfg, const std::string& tag_name, const config & filter) const
|
||||
{
|
||||
return common_matches_filter(cfg, tag_name, filter);
|
||||
}
|
||||
|
||||
bool attack_type::special_matches_filter(const config & cfg, const std::string& tag_name, const config & filter) const
|
||||
{
|
||||
return common_matches_filter(cfg, tag_name, filter);
|
||||
}
|
||||
|
||||
bool attack_type::special_active(const config& special, AFFECTS whom, const std::string& tag_name,
|
||||
const std::string& filter_self) const
|
||||
{
|
||||
|
|
|
@ -155,6 +155,15 @@ private:
|
|||
|
||||
// Configured as a bit field, in case that is useful.
|
||||
enum AFFECTS { AFFECT_SELF=1, AFFECT_OTHER=2, AFFECT_EITHER=3 };
|
||||
/**
|
||||
* Filter a list of abilities or weapon specials
|
||||
* @param cfg config of ability checked
|
||||
* @param tag_name le type of ability who is checked
|
||||
* @param filter config contain list of attribute who are researched in cfg
|
||||
*
|
||||
* @return true if all attribute with ability checked
|
||||
*/
|
||||
bool special_matches_filter(const config & cfg, const std::string& tag_name, const config & filter) const;
|
||||
/**
|
||||
* Filter a list of abilities or weapon specials, removing any entries that don't own
|
||||
* the overwrite_specials attributes.
|
||||
|
|
|
@ -1442,133 +1442,6 @@ void unit::remove_ability_by_id(const std::string& ability)
|
|||
}
|
||||
}
|
||||
|
||||
static bool matches_ability_filter(const config & cfg, const std::string& tag_name, const config & filter)
|
||||
{
|
||||
using namespace utils::config_filters;
|
||||
|
||||
if(!filter["affect_adjacent"].empty()){
|
||||
bool adjacent = cfg.has_child("affect_adjacent");
|
||||
if(filter["affect_adjacent"].to_bool() != adjacent){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!bool_matches_if_present(filter, cfg, "affect_self", true))
|
||||
return false;
|
||||
|
||||
if(!bool_or_empty(filter, cfg, "affect_allies"))
|
||||
return false;
|
||||
|
||||
if(!bool_matches_if_present(filter, cfg, "affect_enemies", false))
|
||||
return false;
|
||||
|
||||
if(!bool_matches_if_present(filter, cfg, "cumulative", false))
|
||||
return false;
|
||||
|
||||
const std::vector<std::string> filter_type = utils::split(filter["tag_name"]);
|
||||
if ( !filter_type.empty() && std::find(filter_type.begin(), filter_type.end(), tag_name) == filter_type.end() )
|
||||
return false;
|
||||
|
||||
if(!string_matches_if_present(filter, cfg, "id", ""))
|
||||
return false;
|
||||
|
||||
if(tag_name == "resistance"){
|
||||
if(!set_includes_if_present(filter, cfg, "apply_to")){
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!string_matches_if_present(filter, cfg, "apply_to", "self")){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!string_matches_if_present(filter, cfg, "overwrite_specials", "none"))
|
||||
return false;
|
||||
|
||||
if(!string_matches_if_present(filter, cfg, "active_on", "both"))
|
||||
return false;
|
||||
|
||||
//for damage only
|
||||
if(!string_matches_if_present(filter, cfg, "replacement_type", ""))
|
||||
return false;
|
||||
|
||||
if(!string_matches_if_present(filter, cfg, "alternative_type", ""))
|
||||
return false;
|
||||
|
||||
//for plague only
|
||||
if(!string_matches_if_present(filter, cfg, "type", ""))
|
||||
return false;
|
||||
|
||||
if(!filter["value"].empty()){
|
||||
if(tag_name == "drains"){
|
||||
if(!int_matches_if_present(filter, cfg, "value", 50)){
|
||||
return false;
|
||||
}
|
||||
} else if(tag_name == "berserk"){
|
||||
if(!int_matches_if_present(filter, cfg, "value", 1)){
|
||||
return false;
|
||||
}
|
||||
} else if(tag_name == "heal_on_hit" || tag_name == "heals" || tag_name == "regenerate" || tag_name == "leadership"){
|
||||
if(!int_matches_if_present(filter, cfg, "value" , 0)){
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!int_matches_if_present(filter, cfg, "value")){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!int_matches_if_present_or_negative(filter, cfg, "add", "sub"))
|
||||
return false;
|
||||
|
||||
if(!int_matches_if_present_or_negative(filter, cfg, "sub", "add"))
|
||||
return false;
|
||||
|
||||
if(!double_matches_if_present(filter, cfg, "multiply"))
|
||||
return false;
|
||||
|
||||
if(!double_matches_if_present(filter, cfg, "divide"))
|
||||
return false;
|
||||
|
||||
//the wml_filter is used in cases where the attribute we are looking for is not
|
||||
//previously listed or to check the contents of the sub_tags ([filter_adjacent],[filter_self],[filter_opponent] etc.
|
||||
//If the checked set does not exactly match the content of the capability, the function returns a false response.
|
||||
auto fwml = filter.optional_child("filter_wml");
|
||||
if (fwml){
|
||||
if(!cfg.matches(*fwml)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Passed all tests.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool unit::ability_matches_filter(const config & cfg, const std::string& tag_name, const config & filter) const
|
||||
{
|
||||
// Handle the basic filter.
|
||||
bool matches = matches_ability_filter(cfg, tag_name, filter);
|
||||
|
||||
// Handle [and], [or], and [not] with in-order precedence
|
||||
for (const config::any_child condition : filter.all_children_range() )
|
||||
{
|
||||
// Handle [and]
|
||||
if ( condition.key == "and" )
|
||||
matches = matches && ability_matches_filter(cfg, tag_name, condition.cfg);
|
||||
|
||||
// Handle [or]
|
||||
else if ( condition.key == "or" )
|
||||
matches = matches || ability_matches_filter(cfg, tag_name, condition.cfg);
|
||||
|
||||
// Handle [not]
|
||||
else if ( condition.key == "not" )
|
||||
matches = matches && !ability_matches_filter(cfg, tag_name, condition.cfg);
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
void unit::remove_ability_by_attribute(const config& filter)
|
||||
{
|
||||
set_attr_changed(UA_ABILITIES);
|
||||
|
|
Loading…
Add table
Reference in a new issue