check alternative_type and replacement_type when filtering on type
Also move them from being attributes of [damage] to [damage_type], to avoid infinite recursion when determining what the damage type should be.
This commit is contained in:
parent
47fec1e90f
commit
9474525612
16 changed files with 235 additions and 80 deletions
|
@ -1,2 +1,2 @@
|
|||
### WML Engine
|
||||
* Add a 'replacement_type' and 'alternative_type' attribute to [damage] to change the type of attack under specific conditions (terrain, time of day, leadership etc...)
|
||||
* Add a [damage_type]'replacement_type' and 'alternative_type' attribute weapon special to change the type of attack under specific conditions (terrain, time of day, leadership etc...)
|
|
@ -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]
|
||||
|
|
|
@ -203,11 +203,11 @@
|
|||
#enddef
|
||||
|
||||
#define WEAPON_SPECIAL_ARCANE
|
||||
[damage]
|
||||
[damage_type]
|
||||
id=arcane_damage
|
||||
name= _ "arcane"
|
||||
description= _ "This attack combines the arcane type with the type of weapon used so that resistance to the arcane type does not penalize the user."
|
||||
special_note=_ "This unit can use the arcane type when the opponent is particularly sensitive to it in relation to the weapon on which it is applied."
|
||||
alternative_type=arcane
|
||||
[/damage]
|
||||
[/damage_type]
|
||||
#enddef
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -133,6 +133,7 @@
|
|||
{BASED_ON_SPECIAL "swarm"}
|
||||
{BASED_ON_SPECIAL "chance_to_hit"}
|
||||
{BASED_ON_SPECIAL "damage"}
|
||||
{BASED_ON_SPECIAL "damage_type"}
|
||||
{BASED_ON_SPECIAL "drains"}
|
||||
{BASED_ON_SPECIAL "heal_on_hit"}
|
||||
{BASED_ON_SPECIAL "berserk"}
|
||||
|
|
|
@ -75,8 +75,19 @@
|
|||
name="damage"
|
||||
max=infinite
|
||||
super="units/unit_type/attack/specials/~value~"
|
||||
[/tag]
|
||||
[tag]
|
||||
name="damage_type"
|
||||
max=infinite
|
||||
super="units/unit_type/attack/specials/~generic~"
|
||||
{SIMPLE_KEY replacement_type string}
|
||||
{SIMPLE_KEY alternative_type string}
|
||||
{DEFAULT_KEY overwrite_specials ability_overwrite none}
|
||||
[tag]
|
||||
name="overwrite"
|
||||
{FILTER_TAG "filter_specials" abilities ()}
|
||||
{SIMPLE_KEY priority real}
|
||||
[/tag]
|
||||
[/tag]
|
||||
[tag]
|
||||
name="drains"
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
# wmllint: no translatables
|
||||
|
||||
#####
|
||||
# API(s) being tested: [event][filter_attack]type=
|
||||
##
|
||||
# Actions:
|
||||
# Give Alice an ability that adds a damage special with addition of arcnae type to all of his weapons.
|
||||
# Define events that use filter_attack matching Alice's arcane type.
|
||||
# Have Alice attack Bob.
|
||||
##
|
||||
# Expected end state:
|
||||
# An event triggers when Alice attacks during side 1's turn because type=arcane detected.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST event_test_filter_attack_type (
|
||||
[event]
|
||||
name=start
|
||||
[object]
|
||||
silent=yes
|
||||
[effect]
|
||||
apply_to=new_ability
|
||||
[abilities]
|
||||
[damage_type]
|
||||
id=test_arcane_damage
|
||||
alternative_type=arcane
|
||||
[/damage_type]
|
||||
[/abilities]
|
||||
[/effect]
|
||||
[filter]
|
||||
id=alice
|
||||
[/filter]
|
||||
[/object]
|
||||
[modify_unit]
|
||||
[filter]
|
||||
[/filter]
|
||||
# Make sure they don't die during the attacks
|
||||
[status]
|
||||
invulnerable=yes
|
||||
[/status]
|
||||
[/modify_unit]
|
||||
{VARIABLE triggers 0}
|
||||
[/event]
|
||||
[event]
|
||||
name=side 1 turn 1
|
||||
[do_command]
|
||||
[move]
|
||||
x=7,13
|
||||
y=3,4
|
||||
[/move]
|
||||
[attack]
|
||||
[source]
|
||||
x,y=13,4
|
||||
[/source]
|
||||
[destination]
|
||||
x,y=13,3
|
||||
[/destination]
|
||||
[/attack]
|
||||
[/do_command]
|
||||
[end_turn][/end_turn]
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=side 2 turn
|
||||
[do_command]
|
||||
[attack]
|
||||
[source]
|
||||
x,y=13,3
|
||||
[/source]
|
||||
[destination]
|
||||
x,y=13,4
|
||||
[/destination]
|
||||
[/attack]
|
||||
[/do_command]
|
||||
[end_turn][/end_turn]
|
||||
[/event]
|
||||
|
||||
# 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 1})}
|
||||
[/event]
|
||||
)}
|
|
@ -1,20 +1,15 @@
|
|||
#textdomain wesnoth-test
|
||||
|
||||
#####
|
||||
# API(s) being tested: [damage]replacement_type=
|
||||
##
|
||||
# Actions:
|
||||
# Give both Alice and Bob 100% chance to hit.
|
||||
# Give Bob one [damage] with replacement_type=fire and two [damage] with replacement_type=cold
|
||||
# change resistance of Bob to arcane to 50% and fire to -100%.
|
||||
# Give Alice one [damage] with replacement_type=cold, two [damage] with replacement_type=arcane and three with replacement_type=fire
|
||||
# and change Alice resistance to cold to -100% and fire to 50%.
|
||||
# Move Alice next to Bob, and have Alice attack Bob.
|
||||
##
|
||||
# Expected end state:
|
||||
# Alice attack with fire and Bob use cold.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "damage_type_test" (
|
||||
# macro used for two tests below
|
||||
#define FILTER_TYPE_BLADE
|
||||
[filter_self]
|
||||
[filter_weapon]
|
||||
type=blade
|
||||
[/filter_weapon]
|
||||
[/filter_self]
|
||||
#enddef
|
||||
|
||||
#define DAMAGE_TYPE_TEST FILTER_WEAPON
|
||||
[event]
|
||||
name=start
|
||||
[modify_unit]
|
||||
|
@ -44,15 +39,18 @@
|
|||
[damage]
|
||||
value=12
|
||||
[/damage]
|
||||
[damage]
|
||||
[damage_type]
|
||||
replacement_type=fire
|
||||
[/damage]
|
||||
[damage]
|
||||
{FILTER_WEAPON}
|
||||
[/damage_type]
|
||||
[damage_type]
|
||||
replacement_type=cold
|
||||
[/damage]
|
||||
[damage]
|
||||
{FILTER_WEAPON}
|
||||
[/damage_type]
|
||||
[damage_type]
|
||||
replacement_type=cold
|
||||
[/damage]
|
||||
{FILTER_WEAPON}
|
||||
[/damage_type]
|
||||
[chance_to_hit]
|
||||
value=100
|
||||
[/chance_to_hit]
|
||||
|
@ -82,24 +80,24 @@
|
|||
[damage]
|
||||
value=12
|
||||
[/damage]
|
||||
[damage]
|
||||
[damage_type]
|
||||
replacement_type=cold
|
||||
[/damage]
|
||||
[damage]
|
||||
[/damage_type]
|
||||
[damage_type]
|
||||
replacement_type=arcane
|
||||
[/damage]
|
||||
[damage]
|
||||
[/damage_type]
|
||||
[damage_type]
|
||||
replacement_type=arcane
|
||||
[/damage]
|
||||
[damage]
|
||||
[/damage_type]
|
||||
[damage_type]
|
||||
replacement_type=fire
|
||||
[/damage]
|
||||
[damage]
|
||||
[/damage_type]
|
||||
[damage_type]
|
||||
replacement_type=fire
|
||||
[/damage]
|
||||
[damage]
|
||||
[/damage_type]
|
||||
[damage_type]
|
||||
replacement_type=fire
|
||||
[/damage]
|
||||
[/damage_type]
|
||||
[chance_to_hit]
|
||||
value=100
|
||||
[/chance_to_hit]
|
||||
|
@ -166,6 +164,42 @@
|
|||
{ASSERT ({VARIABLE_CONDITIONAL b.hitpoints equals 76})}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
#enddef
|
||||
|
||||
#####
|
||||
# API(s) being tested: [damage]replacement_type=
|
||||
##
|
||||
# Actions:
|
||||
# Give both Alice and Bob 100% chance to hit.
|
||||
# Give Bob one [damage] with replacement_type=fire and two [damage] with replacement_type=cold
|
||||
# change resistance of Bob to arcane to 50% and fire to -100%.
|
||||
# Give Alice one [damage] with replacement_type=cold, two [damage] with replacement_type=arcane and three with replacement_type=fire
|
||||
# and change Alice resistance to cold to -100% and fire to 50%.
|
||||
# Move Alice next to Bob, and have Alice attack Bob.
|
||||
##
|
||||
# Expected end state:
|
||||
# Alice attack with fire and Bob use cold.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "damage_type_test" (
|
||||
{DAMAGE_TYPE_TEST ()}
|
||||
)}
|
||||
|
||||
#####
|
||||
# API(s) being tested: [damage]replacement_type=[filter_self][filter_weapon]type=blade
|
||||
##
|
||||
# Actions:
|
||||
# Give both Alice and Bob 100% chance to hit.
|
||||
# Give Bob one [damage] with replacement_type=fire and two [damage] with replacement_type=cold and filter by type=blade
|
||||
# change resistance of Bob to arcane to 50% and fire to -100%.
|
||||
# Give Alice one [damage] with replacement_type=cold, two [damage] with replacement_type=arcane and three with replacement_type=fire
|
||||
# and change Alice resistance to cold to -100% and fire to 50%.
|
||||
# Move Alice next to Bob, and have Alice attack Bob.
|
||||
##
|
||||
# Expected end state:
|
||||
# Alice attack with fire; and Bob use cold because Bob [damage] filter must check type=blade and not the replacement type, that who cause infinite recursion.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "damage_type_with_filter_test" (
|
||||
{DAMAGE_TYPE_TEST {FILTER_TYPE_BLADE}}
|
||||
)}
|
||||
|
||||
#####
|
||||
|
@ -212,9 +246,9 @@
|
|||
[damage]
|
||||
value=12
|
||||
[/damage]
|
||||
[damage]
|
||||
[damage_type]
|
||||
alternative_type=cold
|
||||
[/damage]
|
||||
[/damage_type]
|
||||
[chance_to_hit]
|
||||
value=100
|
||||
[/chance_to_hit]
|
||||
|
@ -244,9 +278,9 @@
|
|||
[damage]
|
||||
value=12
|
||||
[/damage]
|
||||
[damage]
|
||||
[damage_type]
|
||||
alternative_type=fire
|
||||
[/damage]
|
||||
[/damage_type]
|
||||
[chance_to_hit]
|
||||
value=100
|
||||
[/chance_to_hit]
|
||||
|
|
|
@ -134,7 +134,7 @@ void unit_attack::pre_show(window& window)
|
|||
defw_type_second = ", " + string_table["type_" + defw_type_second];
|
||||
}
|
||||
|
||||
const std::set<std::string> checking_tags_other = {"disable", "berserk", "drains", "heal_on_hit", "plague", "slow", "petrifies", "firststrike", "poison"};
|
||||
const std::set<std::string> checking_tags_other = {"damage_type", "disable", "berserk", "drains", "heal_on_hit", "plague", "slow", "petrifies", "firststrike", "poison"};
|
||||
std::string attw_specials = attacker_weapon.weapon_specials();
|
||||
std::string attw_specials_dmg = attacker_weapon.weapon_specials_value({"leadership", "damage"});
|
||||
std::string attw_specials_atk = attacker_weapon.weapon_specials_value({"attacks", "swarm"});
|
||||
|
|
|
@ -1197,7 +1197,7 @@ static std::vector<std::string> damage_type_list(const unit_ability_list& abil_l
|
|||
*/
|
||||
std::pair<std::string, std::string> attack_type::damage_type() const
|
||||
{
|
||||
unit_ability_list abil_list = get_specials_and_abilities("damage");
|
||||
unit_ability_list abil_list = get_specials_and_abilities("damage_type");
|
||||
if(abil_list.empty()){
|
||||
return {type(), ""};
|
||||
}
|
||||
|
@ -1207,6 +1207,9 @@ std::pair<std::string, std::string> attack_type::damage_type() const
|
|||
std::string type_damage, sec_type_damage;
|
||||
type_damage = !type_list.empty() ? type_list.front() : type();
|
||||
sec_type_damage = !added_type_list.empty() ? added_type_list.front() : "";
|
||||
if(!sec_type_damage.empty()){
|
||||
sec_type_damage = type_damage != sec_type_damage ? sec_type_damage: "";
|
||||
}
|
||||
return {type_damage, sec_type_damage};
|
||||
}
|
||||
|
||||
|
@ -1273,11 +1276,12 @@ namespace { // Helpers for attack_type::special_active()
|
|||
* (normally a [filter_*] child) of the provided filter.
|
||||
* @param[in] u A unit to filter.
|
||||
* @param[in] u2 Another unit to filter.
|
||||
* @param[in] loc The presumed location of @a un_it.
|
||||
* @param[in] loc The presumed location of @a unit.
|
||||
* @param[in] weapon The attack_type to filter.
|
||||
* @param[in] filter The filter containing the child filter to use.
|
||||
* @param[in] for_listing
|
||||
* @param[in] child_tag The tag of the child filter to use.
|
||||
* @param[in] tag_name Parameter used for don't have infinite recusion for some filter attribute.
|
||||
*/
|
||||
static bool special_unit_matches(unit_const_ptr & u,
|
||||
unit_const_ptr & u2,
|
||||
|
@ -1285,7 +1289,7 @@ namespace { // Helpers for attack_type::special_active()
|
|||
const_attack_ptr weapon,
|
||||
const config & filter,
|
||||
const bool for_listing,
|
||||
const std::string & child_tag)
|
||||
const std::string & child_tag, const std::string& tag_name)
|
||||
{
|
||||
if (for_listing && !loc.valid())
|
||||
// The special's context was set to ignore this unit, so assume we pass.
|
||||
|
@ -1312,7 +1316,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, tag_name) )
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1810,13 +1814,20 @@ bool attack_type::special_active_impl(
|
|||
const config& special_backstab = special["backstab"].to_bool() ? cfg : special;
|
||||
|
||||
// Filter the units involved.
|
||||
if (!special_unit_matches(self, other, self_loc, self_attack, special, is_for_listing, filter_self))
|
||||
//If filter concerns the unit on which special is applied,
|
||||
//then the type of special must be entered to avoid calling
|
||||
//the function of this special in matches_filter()
|
||||
std::string self_tag_name = whom_is_self ? tag_name : "";
|
||||
if (!special_unit_matches(self, other, self_loc, self_attack, special, is_for_listing, filter_self, self_tag_name))
|
||||
return false;
|
||||
if (!special_unit_matches(other, self, other_loc, other_attack, special_backstab, is_for_listing, "filter_opponent"))
|
||||
std::string opp_tag_name = !whom_is_self ? tag_name : "";
|
||||
if (!special_unit_matches(other, self, other_loc, other_attack, special_backstab, is_for_listing, "filter_opponent", opp_tag_name))
|
||||
return false;
|
||||
if (!special_unit_matches(att, def, att_loc, att_weapon, special, is_for_listing, "filter_attacker"))
|
||||
std::string att_tag_name = is_attacker ? tag_name : "";
|
||||
if (!special_unit_matches(att, def, att_loc, att_weapon, special, is_for_listing, "filter_attacker", att_tag_name))
|
||||
return false;
|
||||
if (!special_unit_matches(def, att, def_loc, def_weapon, special, is_for_listing, "filter_defender"))
|
||||
std::string def_tag_name = !is_attacker ? tag_name : "";
|
||||
if (!special_unit_matches(def, att, def_loc, def_weapon, special, is_for_listing, "filter_defender", def_tag_name))
|
||||
return false;
|
||||
|
||||
const auto adjacent = get_adjacent_tiles(self_loc);
|
||||
|
|
|
@ -101,19 +101,17 @@ 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, const std::string& tag_name)
|
||||
{
|
||||
const std::vector<std::string>& filter_range = utils::split(filter["range"]);
|
||||
const std::set<std::string> filter_range = utils::split_set(filter["range"].str());
|
||||
const std::string& filter_damage = filter["damage"];
|
||||
const std::string& filter_attacks = filter["number"];
|
||||
const std::string& filter_accuracy = filter["accuracy"];
|
||||
const std::string& filter_parry = filter["parry"];
|
||||
const std::string& filter_movement = filter["movement_used"];
|
||||
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::set<std::string> filter_name = utils::split_set(filter["name"].str());
|
||||
const std::set<std::string> filter_type = utils::split_set(filter["type"].str());
|
||||
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"]);
|
||||
|
@ -122,7 +120,7 @@ static bool matches_simple_filter(const attack_type & attack, const config & fil
|
|||
const std::vector<std::string> filter_special_type_active = utils::split(filter["special_type_active"]);
|
||||
const std::string filter_formula = filter["formula"];
|
||||
|
||||
if ( !filter_range.empty() && std::find(filter_range.begin(), filter_range.end(), attack.range()) == filter_range.end() )
|
||||
if ( !filter_range.empty() && filter_range.count(attack.range()) == 0 )
|
||||
return false;
|
||||
|
||||
if ( !filter_damage.empty() && !in_ranges(attack.damage(), utils::parse_ranges_unsigned(filter_damage)) )
|
||||
|
@ -143,21 +141,19 @@ static bool matches_simple_filter(const attack_type & attack, const config & fil
|
|||
if (!filter_attacks_used.empty() && !in_ranges(attack.attacks_used(), utils::parse_ranges_unsigned(filter_attacks_used)))
|
||||
return false;
|
||||
|
||||
if ( !filter_name.empty() && std::find(filter_name.begin(), filter_name.end(), attack.id()) == filter_name.end() )
|
||||
if ( !filter_name.empty() && filter_name.count(attack.id()) == 0)
|
||||
return false;
|
||||
|
||||
if ( !filter_type.empty() && std::find(filter_type.begin(), filter_type.end(), attack.type()) == 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()){
|
||||
if ( std::find(filter_replacement_type.begin(), filter_replacement_type.end(), damage_type.first) == filter_replacement_type.end() ){
|
||||
if (!filter_type.empty()){
|
||||
//if special is type "damage_type" then check attack.type() only for don't have infinite recursion by calling damage_type() below.
|
||||
if(tag_name == "damage_type"){
|
||||
if (filter_type.count(attack.type()) == 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!filter_alternative_type.empty()){
|
||||
if ( std::find(filter_alternative_type.begin(), filter_alternative_type.end(), damage_type.second) == filter_alternative_type.end() ){
|
||||
} else {
|
||||
//if the type is different from "damage_type" then damage_type() can be called for safe checking.
|
||||
std::pair<std::string, std::string> damage_type = attack.damage_type();
|
||||
if (filter_type.count(damage_type.first) == 0 && filter_type.count(damage_type.second) == 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -261,25 +257,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, const std::string& tag_name) const
|
||||
{
|
||||
// Handle the basic filter.
|
||||
bool matches = matches_simple_filter(*this, filter);
|
||||
bool matches = matches_simple_filter(*this, filter, tag_name);
|
||||
|
||||
// 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, tag_name);
|
||||
|
||||
// Handle [or]
|
||||
else if ( condition.key == "or" )
|
||||
matches = matches || matches_filter(condition.cfg);
|
||||
matches = matches || matches_filter(condition.cfg, tag_name);
|
||||
|
||||
// Handle [not]
|
||||
else if ( condition.key == "not" )
|
||||
matches = matches && !matches_filter(condition.cfg);
|
||||
matches = matches && !matches_filter(condition.cfg, tag_name);
|
||||
}
|
||||
|
||||
return matches;
|
||||
|
|
|
@ -124,7 +124,7 @@ public:
|
|||
|
||||
// In unit_types.cpp:
|
||||
|
||||
bool matches_filter(const config& filter) const;
|
||||
bool matches_filter(const config& filter, const std::string& tag_name = "") const;
|
||||
bool apply_modification(const config& cfg);
|
||||
bool describe_modification(const config& cfg,std::string* description);
|
||||
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -1803,7 +1803,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
const std::set<std::string> checking_tags_{"attacks", "damage", "chance_to_hit", "berserk", "swarm", "drains", "heal_on_hit", "plague", "slow", "petrifies", "firststrike", "poison"};
|
||||
const std::set<std::string> checking_tags_{"attacks", "damage", "chance_to_hit", "berserk", "swarm", "drains", "heal_on_hit", "plague", "slow", "petrifies", "firststrike", "poison", "damage_type"};
|
||||
/**
|
||||
* Check if an ability is active.
|
||||
* @param ability The type (tag name) of the ability
|
||||
|
|
|
@ -155,6 +155,7 @@
|
|||
0 test_ability_id_not_active
|
||||
0 event_test_filter_attack
|
||||
0 event_test_filter_attack_no_defense
|
||||
0 event_test_filter_attack_type
|
||||
0 event_test_filter_attack_specials
|
||||
0 event_test_filter_attack_on_moveto
|
||||
0 event_test_filter_attack_opponent_weapon_condition
|
||||
|
@ -335,6 +336,7 @@
|
|||
0 test_remove_ability_by_filter
|
||||
0 test_overwrite_specials_filter
|
||||
0 damage_type_test
|
||||
0 damage_type_with_filter_test
|
||||
0 damage_secondary_type_test
|
||||
0 swarms_filter_student_by_type
|
||||
0 swarms_effects_not_checkable
|
||||
|
|
Loading…
Add table
Reference in a new issue