Skip to content

Commit

Permalink
replace alternative/replacement_type with 'type' in [filter_attack/we…
Browse files Browse the repository at this point in the history
…apon]

To respond to an objection from @CelticMinstrel in wesnoth#7865 (comment), I moved alternative/replacement_type in matches_ability_filter and checking will be done with the 'type' filter in attack_type ::matches_filter() with security, if the function is called from a weapons specials([filter_self/opponent][filter_weapon]) then the type encoded in the type encoded in [damage] will not be checked to avoid a recursive loop.
  • Loading branch information
newfrenchy83 committed Oct 30, 2023
1 parent 50a21a2 commit 9415662
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
3 changes: 3 additions & 0 deletions data/schema/filters/abilities.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
2 changes: 0 additions & 2 deletions data/schema/filters/weapon.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
2 changes: 1 addition & 1 deletion src/units/abilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
29 changes: 18 additions & 11 deletions src/units/attack_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string>& filter_range = utils::split(filter["range"]);
const std::string& filter_damage = filter["damage"];
Expand All @@ -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<std::string> filter_name = utils::split(filter["name"]);
const std::vector<std::string> filter_type = utils::split(filter["type"]);
const std::vector<std::string> filter_replacement_type = utils::split(filter["replacement_type"]);
const std::vector<std::string> filter_alternative_type = utils::split(filter["alternative_type"]);
const std::vector<std::string> filter_special = utils::split(filter["special"]);
const std::vector<std::string> filter_special_id = utils::split(filter["special_id"]);
const std::vector<std::string> filter_special_type = utils::split(filter["special_type"]);
Expand Down Expand Up @@ -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<std::string, std::string> 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<std::string, std::string> damage_type = attack.damage_type();
if(!filter_replacement_type.empty()){
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/units/attack_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class attack_type : public std::enable_shared_from_this<attack_type>

// 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);

Expand Down
11 changes: 11 additions & 0 deletions src/units/unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand Down

0 comments on commit 9415662

Please sign in to comment.