diff --git a/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_ability_special_id_active.cfg b/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_ability_special_id_active.cfg index 96659a53efc5..ea65d2eed3f6 100644 --- a/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_ability_special_id_active.cfg +++ b/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_ability_special_id_active.cfg @@ -7,7 +7,7 @@ # Give bob a ability weapon special with an id. ## # Expected end state: -# special_id_active correctly doesn't find a unit with that weapon special id, since it's given via an ability. +# special_id_active correctly find a unit with that weapon special id. ##### {GENERIC_UNIT_TEST "filter_ability_special_id_active" ( [event] @@ -31,13 +31,11 @@ [/object] {ASSERT ( - [not] - [have_unit] - [has_attack] - special_id_active=test_cth - [/has_attack] - [/have_unit] - [/not] + [have_unit] + [has_attack] + special_id_active=test_cth + [/has_attack] + [/have_unit] )} {SUCCEED} diff --git a/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_special_id_active.cfg b/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_special_id_active.cfg index 0720829f5495..99fd2acc54d7 100644 --- a/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_special_id_active.cfg +++ b/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_special_id_active.cfg @@ -4,10 +4,10 @@ # API(s) being tested: [has_attack]special_id_active= ## # Actions: -# Give bob a weapon special with an id. +# Give bob a weapon special with an id active if owner is an orc. ## # Expected end state: -# special_id_active correctly finds a unit with that weapon special id. +# special_id_active correctly finds a unit with that weapon special id, bob match condition for what special be active. ##### {GENERIC_UNIT_TEST "filter_special_id_active" ( [event] @@ -21,6 +21,9 @@ [chance_to_hit] id=test_cth value=100 + [filter_self] + race=orc + [/filter_self] [/chance_to_hit] [/set_specials] [/effect] diff --git a/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_special_id_active_no_active.cfg b/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_special_id_active_no_active.cfg new file mode 100644 index 000000000000..5d44c95895cf --- /dev/null +++ b/data/test/scenarios/wml_tests/ScenarioWML/EventWML/ActionWML/ConditionalActionsWML/filter_special_id_active_no_active.cfg @@ -0,0 +1,47 @@ +#textdomain wesnoth-test + +##### +# API(s) being tested: [has_attack]special_id_active= +## +# Actions: +# Give bob a weapon special with an id active if owner is an elf. +## +# Expected end state: +# special_id_active cannot finds a unit with that weapon special id, because bob don't match conditions for special be active +##### +{GENERIC_UNIT_TEST "filter_special_id_active_when_no_active" ( + [event] + name=start + + [object] + silent=yes + [effect] + apply_to=attack + [set_specials] + [chance_to_hit] + id=test_cth + value=100 + [filter_self] + race=elf + [/filter_self] + [/chance_to_hit] + [/set_specials] + [/effect] + [filter] + id=bob + [/filter] + [/object] + + {ASSERT ( + [not] + [have_unit] + [has_attack] + special_id_active=test_cth + [/has_attack] + [/have_unit] + [/not] + )} + + {SUCCEED} + [/event] +)} diff --git a/data/test/scenarios/wml_tests/UnitsWML/AbilitiesWML/special_damage_type.cfg b/data/test/scenarios/wml_tests/UnitsWML/AbilitiesWML/special_damage_type.cfg index d332eda08910..ce70471197f5 100644 --- a/data/test/scenarios/wml_tests/UnitsWML/AbilitiesWML/special_damage_type.cfg +++ b/data/test/scenarios/wml_tests/UnitsWML/AbilitiesWML/special_damage_type.cfg @@ -282,20 +282,7 @@ [/event] )} -##### -# API(s) being tested: [filter_self][has_attack]type= in [damage_type] -## -# Actions: -# Give Alice an ability that changes all damage types to arcane if Alice has a blade attack -# Define events that use filter_attack matching Alice's arcane type. -# Have Alice attack Bob during side 1's turn -# Have Bob attack Alice during side 2's turn -## -# Expected end state: -# BROKE STRICT due to infinite recursion. -# The test reaches turn 2 without crashing; this tests for a C++ crash due to infinite recursion in the filters. -##### -{COMMON_KEEP_A_B_UNIT_TEST event_test_filter_damage_type_recursion ( +#define RECURSION_DAMAGE_TYPE_TEST WEAPON [event] name=start [object] @@ -333,6 +320,7 @@ [test_do_attack_by_id] attacker=alice defender=bob + weapon={WEAPON} [/test_do_attack_by_id] [end_turn][/end_turn] [/event] @@ -345,6 +333,23 @@ [/test_do_attack_by_id] [end_turn][/end_turn] [/event] +#enddef + +##### +# API(s) being tested: [filter_self][has_attack]type= in [damage_type] +## +# Actions: +# Give Alice an ability that changes all damage types to arcane if Alice has a blade attack +# Define events that use filter_attack matching Alice's arcane type. +# Have Alice attack Bob with melee weapon during side 1's turn +# Have Bob attack Alice during side 2's turn +## +# Expected end state: +# BROKE STRICT due to infinite recursion. +# The test reaches turn 2 without crashing and event trigered; this tests for a C++ crash due to infinite recursion in the filters. +##### +{COMMON_KEEP_A_B_UNIT_TEST event_test_filter_damage_type_recursion ( + {RECURSION_DAMAGE_TYPE_TEST 0} # Event when Alice attacks [event] @@ -362,3 +367,38 @@ {RETURN ({VARIABLE_CONDITIONAL triggers equals 1})} [/event] )} + +##### +# API(s) being tested: [filter_self][has_attack]type= in [damage_type] +## +# Actions: +# Give Alice an ability that changes all damage types to arcane if Alice has a blade attack +# Define events that use filter_attack matching Alice's arcane type. +# Have Alice attack Bob with ranged weapon during side 1's turn +# Have Bob attack Alice during side 2's turn +## +# Expected end state: +# BROKE STRICT due to infinite recursion. +# The test reaches turn 2 without crashing and event no trigered because no blade attack exist; this tests for a C++ crash due to infinite recursion in the filters. +##### +{COMMON_KEEP_A_B_UNIT_TEST event_test_failed_filter_damage_type_recursion ( + {RECURSION_DAMAGE_TYPE_TEST 1} + + # Event when Alice attacks + [event] + name=attack + first_time_only=no + [filter_attack] + type=arcane + [/filter_attack] + {ASSERT ({VARIABLE_CONDITIONAL side_number equals 1})} + {ASSERT ({VARIABLE_CONDITIONAL triggers equals 0})} + {VARIABLE_OP triggers add 1} + [/event] + [event] + name=turn 2 + {RETURN ({VARIABLE_CONDITIONAL triggers equals 0})} + [/event] +)} + +#undef RECURSION_DAMAGE_TYPE_TEST diff --git a/src/units/filter.cpp b/src/units/filter.cpp index 45740e11ffff..9b7d5d74cefc 100644 --- a/src/units/filter.cpp +++ b/src/units/filter.cpp @@ -818,6 +818,7 @@ void unit_filter_compound::fill(const vconfig& cfg) else if (child.first == "has_attack") { create_child(child.second, [](const vconfig& c, const unit_filter_args& args) { for(const attack_type& a : args.u.attacks()) { + auto ctx = a.specials_context((args.u).shared_from_this(), args.loc, true); if(a.matches_filter(c.get_parsed_config())) { return true; } diff --git a/wml_test_schedule b/wml_test_schedule index 9d1bb64e457a..48111cac01d8 100644 --- a/wml_test_schedule +++ b/wml_test_schedule @@ -393,6 +393,7 @@ 0 damage_type_apply_to_both_filter_self_opponent 0 damage_type_apply_to_attacker_filter_attacker_defender 9 event_test_filter_damage_type_recursion +9 event_test_failed_filter_damage_type_recursion 9 four_cycle_recursion_branching 9 four_cycle_recursion_by_id 9 four_cycle_recursion_by_tagname @@ -407,6 +408,7 @@ 0 swarms_filter_student_by_type 0 swarms_effects_not_checkable 0 filter_special_id_active +0 filter_special_id_active_when_no_active 0 filter_ability_special_id_active 0 filter_special_id_not_exists 0 special_id_active_lua_function