From bfaf4322e4ae3a2ac367862fa98c1ebbde42f469 Mon Sep 17 00:00:00 2001 From: newfrenchy83 Date: Tue, 31 Oct 2023 11:41:28 +0100 Subject: [PATCH] extent can_bool to resistance and leadership and using 'type_changed_by_special' in replacement to type for check type changed by damage The addition of 'type_changed_by_special' is a temporary solution to allow wml authors to be able to check types modified by damage ([filter_opponent)) in specials without systematically risking infinite recursion. The introduction in wesnoth 1.19 of [filter_specials] in [filter_attack/weapon] should make it obsolete. --- data/schema/filters/weapon.cfg | 8 ++++++++ data/schema/units/abilities.cfg | 8 ++++---- data/schema/units/specials.cfg | 8 ++++---- src/units/abilities.cpp | 2 +- src/units/attack_type.cpp | 12 +++++++++++- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/data/schema/filters/weapon.cfg b/data/schema/filters/weapon.cfg index 5084885a061a3..8443e34bf96f4 100644 --- a/data/schema/filters/weapon.cfg +++ b/data/schema/filters/weapon.cfg @@ -21,3 +21,11 @@ {FILTER_BOOLEAN_OPS weapon} [/tag] +[tag] + name="$filter_weapon_by_special" + max=0 + super="$filter_weapon" + {SIMPLE_KEY type_changed_by_special string_list} + {FILTER_BOOLEAN_OPS weapon} +[/tag] + diff --git a/data/schema/units/abilities.cfg b/data/schema/units/abilities.cfg index 7b2c82862f708..5e12131b7bf5d 100644 --- a/data/schema/units/abilities.cfg +++ b/data/schema/units/abilities.cfg @@ -83,8 +83,8 @@ name="resistance" max=infinite super="units/unit_type/abilities/~value~" - {FILTER_TAG "filter_weapon" weapon ()} - {FILTER_TAG "filter_second_weapon" weapon ()} + {FILTER_TAG "filter_weapon" weapon_by_special ()} + {FILTER_TAG "filter_second_weapon" weapon_by_special ()} [/tag] [tag] name="leadership" @@ -95,8 +95,8 @@ {SIMPLE_KEY sub f_int} {SIMPLE_KEY multiply f_int} {SIMPLE_KEY divide f_int} - {FILTER_TAG "filter_weapon" weapon ()} - {FILTER_TAG "filter_second_weapon" weapon ()} + {FILTER_TAG "filter_weapon" weapon_by_special ()} + {FILTER_TAG "filter_second_weapon" weapon_by_special ()} [/tag] [tag] name="illuminates" diff --git a/data/schema/units/specials.cfg b/data/schema/units/specials.cfg index 799b067616be1..ad6e2cd480a1d 100644 --- a/data/schema/units/specials.cfg +++ b/data/schema/units/specials.cfg @@ -14,10 +14,10 @@ {FILTER_TAG "filter_adjacent" adjacent ()} {FILTER_TAG "filter_adjacent_location" adjacent_location ()} - {FILTER_TAG "filter_self" unit {FILTER_TAG "filter_weapon" weapon ()}} - {FILTER_TAG "filter_opponent" unit {FILTER_TAG "filter_weapon" weapon ()}} - {FILTER_TAG "filter_attacker" unit {FILTER_TAG "filter_weapon" weapon ()}} - {FILTER_TAG "filter_defender" unit {FILTER_TAG "filter_weapon" weapon ()}} + {FILTER_TAG "filter_self" unit {FILTER_TAG "filter_weapon" weapon_by_special ()}} + {FILTER_TAG "filter_opponent" unit {FILTER_TAG "filter_weapon" weapon_by_special ()}} + {FILTER_TAG "filter_attacker" unit {FILTER_TAG "filter_weapon" weapon_by_special ()}} + {FILTER_TAG "filter_defender" unit {FILTER_TAG "filter_weapon" weapon_by_special ()}} {WML_MERGE_KEYS} [/tag] # A few specials inheriting from ~generic~ are included here so that unit abilities can then inherit from them. diff --git a/src/units/abilities.cpp b/src/units/abilities.cpp index e6a525060b7cf..5ae9e2ef22f28 100644 --- a/src/units/abilities.cpp +++ b/src/units/abilities.cpp @@ -468,7 +468,7 @@ bool unit::ability_affects_weapon(const config& cfg, const_attack_ptr weapon, bo if(!weapon) { return false; } - return weapon->matches_filter(filter); + return weapon->matches_filter(filter, true); } bool unit::has_ability_type(const std::string& ability) const diff --git a/src/units/attack_type.cpp b/src/units/attack_type.cpp index 9db9f21b16dff..8c3109b94f42c 100644 --- a/src/units/attack_type.cpp +++ b/src/units/attack_type.cpp @@ -144,7 +144,7 @@ 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()){ + if (!filter_type.empty()){ if(can_loop){ if (std::find(filter_type.begin(), filter_type.end(), attack.type()) == filter_type.end() ){ return false; @@ -157,6 +157,16 @@ static bool matches_simple_filter(const attack_type & attack, const config & fil } } + if(can_loop){ + const std::vector filter_modified_type = utils::split(filter["type_changed_by_special"]); + if (!filter_modified_type.empty()){ + std::pair damage_type = attack.damage_type(); + if ((std::find(filter_modified_type.begin(), filter_modified_type.end(), damage_type.first) == filter_modified_type.end()) && (std::find(filter_modified_type.begin(), filter_modified_type.end(), damage_type.second) == filter_modified_type.end())){ + return false; + } + } + } + if(!filter_special.empty()) { deprecated_message("special=", DEP_LEVEL::PREEMPTIVE, {1, 17, 0}, "Please use special_id or special_type instead"); bool found = false;