diff --git a/data/campaigns/Under_the_Burning_Suns/scenarios/03_Stirring_in_the_Night.cfg b/data/campaigns/Under_the_Burning_Suns/scenarios/03_Stirring_in_the_Night.cfg index 621cf6a560369..b3c8e6903053e 100644 --- a/data/campaigns/Under_the_Burning_Suns/scenarios/03_Stirring_in_the_Night.cfg +++ b/data/campaigns/Under_the_Burning_Suns/scenarios/03_Stirring_in_the_Night.cfg @@ -743,13 +743,10 @@ [effect] apply_to=attack range=melee - # the type=arcane or alternative_type=arcane must be filtered in case Garak picked up the holy + # Exclude arcane attacks in case Garak picked up the holy # water in the second scenario - in that case he gets to keep it [not] type=arcane - [or] - alternative_type=arcane - [/or] [/not] set_type=fire [/effect] diff --git a/data/schema/filters/abilities.cfg b/data/schema/filters/abilities.cfg index 16ccb956d9ce6..b0c94a7ab8e51 100644 --- a/data/schema/filters/abilities.cfg +++ b/data/schema/filters/abilities.cfg @@ -6,6 +6,9 @@ {SIMPLE_KEY tag_name string_list} {SIMPLE_KEY overwrite_specials ability_overwrite} {SIMPLE_KEY apply_to string_list} + {SIMPLE_KEY type string_list} + {SIMPLE_KEY replacement_type string_list} + {SIMPLE_KEY alternative_type string_list} {SIMPLE_KEY active_on ability_context} {SIMPLE_KEY value s_int_range_list} {SIMPLE_KEY add s_int_range_list} diff --git a/data/schema/filters/weapon.cfg b/data/schema/filters/weapon.cfg index 7e2e082e34cc7..5084885a061a3 100644 --- a/data/schema/filters/weapon.cfg +++ b/data/schema/filters/weapon.cfg @@ -5,8 +5,6 @@ {SIMPLE_KEY range string_list} {SIMPLE_KEY name string_list} {SIMPLE_KEY type string_list} - {SIMPLE_KEY replacement_type string_list} - {SIMPLE_KEY alternative_type string_list} {SIMPLE_KEY special string_list} {SIMPLE_KEY special_active string_list} {SIMPLE_KEY special_id string_list} diff --git a/src/units/abilities.cpp b/src/units/abilities.cpp index 327e181055446..e6a525060b7cf 100644 --- a/src/units/abilities.cpp +++ b/src/units/abilities.cpp @@ -1312,7 +1312,7 @@ namespace { // Helpers for attack_type::special_active() // Check for a weapon match. if (auto filter_weapon = filter_child->optional_child("filter_weapon") ) { - if ( !weapon || !weapon->matches_filter(*filter_weapon) ) + if ( !weapon || !weapon->matches_filter(*filter_weapon, true) ) return false; } diff --git a/src/units/attack_type.cpp b/src/units/attack_type.cpp index d809eeeaaf6af..9a03cbd57d097 100644 --- a/src/units/attack_type.cpp +++ b/src/units/attack_type.cpp @@ -101,7 +101,7 @@ std::string attack_type::accuracy_parry_description() const * Returns whether or not *this matches the given @a filter, ignoring the * complexities introduced by [and], [or], and [not]. */ -static bool matches_simple_filter(const attack_type & attack, const config & filter) +static bool matches_simple_filter(const attack_type & attack, const config & filter, bool can_loop) { const std::vector& filter_range = utils::split(filter["range"]); const std::string& filter_damage = filter["damage"]; @@ -112,8 +112,6 @@ static bool matches_simple_filter(const attack_type & attack, const config & fil const std::string& filter_attacks_used = filter["attacks_used"]; const std::vector filter_name = utils::split(filter["name"]); const std::vector filter_type = utils::split(filter["type"]); - const std::vector filter_replacement_type = utils::split(filter["replacement_type"]); - const std::vector filter_alternative_type = utils::split(filter["alternative_type"]); const std::vector filter_special = utils::split(filter["special"]); const std::vector filter_special_id = utils::split(filter["special_id"]); const std::vector filter_special_type = utils::split(filter["special_type"]); @@ -146,9 +144,18 @@ static bool matches_simple_filter(const attack_type & attack, const config & fil if ( !filter_name.empty() && std::find(filter_name.begin(), filter_name.end(), attack.id()) == filter_name.end() ) return false; - if ( !filter_type.empty() && std::find(filter_type.begin(), filter_type.end(), attack.type()) == filter_type.end() ) - return false; - + if ( !filter_type.empty()){ + if(can_loop){ + if (std::find(filter_type.begin(), filter_type.end(), attack.type()) == filter_type.end() ){ + return false; + } + } else { + std::pair damage_type = attack.damage_type(); + if ((std::find(filter_type.begin(), filter_type.end(), damage_type.first) == filter_type.end()) && (std::find(filter_type.begin(), filter_type.end(), damage_type.second) == filter_type.end())){ + return false; + } + } + } if(!filter_alternative_type.empty() || !filter_replacement_type.empty()){ std::pair damage_type = attack.damage_type(); if(!filter_replacement_type.empty()){ @@ -261,25 +268,25 @@ static bool matches_simple_filter(const attack_type & attack, const config & fil /** * Returns whether or not *this matches the given @a filter. */ -bool attack_type::matches_filter(const config& filter) const +bool attack_type::matches_filter(const config& filter, bool can_loop) const { // Handle the basic filter. - bool matches = matches_simple_filter(*this, filter); + bool matches = matches_simple_filter(*this, filter, can_loop); // 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 && matches_filter(condition.cfg); + matches = matches && matches_filter(condition.cfg, can_loop); // Handle [or] else if ( condition.key == "or" ) - matches = matches || matches_filter(condition.cfg); + matches = matches || matches_filter(condition.cfg, can_loop); // Handle [not] else if ( condition.key == "not" ) - matches = matches && !matches_filter(condition.cfg); + matches = matches && !matches_filter(condition.cfg, can_loop); } return matches; diff --git a/src/units/attack_type.hpp b/src/units/attack_type.hpp index 6073573e04868..6be9874f6f610 100644 --- a/src/units/attack_type.hpp +++ b/src/units/attack_type.hpp @@ -124,7 +124,7 @@ class attack_type : public std::enable_shared_from_this // In unit_types.cpp: - bool matches_filter(const config& filter) const; + bool matches_filter(const config& filter, bool can_loop = false) const; bool apply_modification(const config& cfg); bool describe_modification(const config& cfg,std::string* description); diff --git a/src/units/unit.cpp b/src/units/unit.cpp index 6d31888f203d0..d37dc6c4220a7 100644 --- a/src/units/unit.cpp +++ b/src/units/unit.cpp @@ -1460,6 +1460,17 @@ static bool matches_ability_filter(const config & cfg, const std::string& tag_na 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()){ bool has_other_key = (!cfg["add"].empty() || !cfg["sub"].empty() || !cfg["multiply"].empty() || !cfg["divide"].empty()); if(!has_other_key){