diff --git a/src/units/abilities.cpp b/src/units/abilities.cpp index 38152e40612..f5d865c51ed 100644 --- a/src/units/abilities.cpp +++ b/src/units/abilities.cpp @@ -1297,48 +1297,41 @@ static bool overwrite_special_affects(const config& special) return (apply_to == "one_side" || apply_to == "both_sides"); } -unit_ability_list attack_type::overwrite_special_checking(const std::string& ability, const unit_ability_list& temp_list, const unit_ability_list& abil_list, const std::string& filter_self, bool is_special) const +unit_ability_list attack_type::overwrite_special_checking(const std::string& ability, unit_ability_list input, unit_ability_list overwriters, const std::string& filter_self, bool is_special) const { - bool overwrite_self = false; - bool overwrite_opponent = false; - bool overwrite_either = false; - - for(const auto& i : abil_list) { - if((*i.ability_cfg)["overwrite_specials"] == "both_sides") { - overwrite_either = true; - break; - } - if((*i.ability_cfg)["overwrite_specials"] == "one_side" && special_active_impl(shared_from_this(), other_attack_, *i.ability_cfg, AFFECT_SELF, ability, filter_self) && !overwrite_self) { - overwrite_self = true; - } - if((*i.ability_cfg)["overwrite_specials"] == "one_side" && special_active_impl(other_attack_, shared_from_this(), *i.ability_cfg, AFFECT_OTHER, ability, filter_self) && !overwrite_opponent) { - overwrite_opponent = true; + for(unit_ability_list::iterator i = overwriters.begin(); i != overwriters.end();) { + if(!overwrite_special_affects(*i->ability_cfg)) { + i = overwriters.erase(i); + } else { + ++i; } } - if(!overwrite_either && !overwrite_self && !overwrite_opponent){ - return temp_list; + if(overwriters.empty()){ + return input; } - if(!overwrite_either && overwrite_self && overwrite_opponent){ - overwrite_either = true; - } - - // At this point we need to return a changed list, so create a non-const one to return - unit_ability_list overwrite_list; - for(const auto& i : temp_list) { - bool overwrite = false; - if(overwrite_either){ - overwrite = !is_special && overwrite_special_affects(*i.ability_cfg); - } else if(overwrite_self){ - overwrite = (!is_special && overwrite_special_affects(*i.ability_cfg)) || special_active_impl(other_attack_, shared_from_this(), *i.ability_cfg, AFFECT_OTHER, ability, filter_self); - } else if(overwrite_opponent){ - overwrite = (!is_special && overwrite_special_affects(*i.ability_cfg)) || special_active_impl(shared_from_this(), other_attack_, *i.ability_cfg, AFFECT_SELF, ability, filter_self); - } - if(overwrite) { - overwrite_list.emplace_back(i); + for(const auto& i : overwriters) { + bool affect_side = ((*i.ability_cfg)["overwrite_specials"] == "one_side"); + for(unit_ability_list::iterator j = input.begin(); j != input.end();) { + bool is_overwritable = (is_special || !overwrite_special_affects(*j->ability_cfg)); + bool one_side_overwritable = true; + if(affect_side && is_overwritable){ + if(special_active_impl(shared_from_this(), other_attack_, *i.ability_cfg, AFFECT_SELF, ability, filter_self)){ + one_side_overwritable = special_active_impl(shared_from_this(), other_attack_, *j->ability_cfg, AFFECT_SELF, ability, filter_self); + } + else if(special_active_impl(other_attack_, shared_from_this(), *i.ability_cfg, AFFECT_OTHER, ability, filter_self)){ + one_side_overwritable = special_active_impl(other_attack_, shared_from_this(), *j->ability_cfg, AFFECT_OTHER, ability, filter_self); + } + } + is_overwritable = is_overwritable && one_side_overwritable; + if(is_overwritable) { + j = input.erase(j); + } else { + ++j; + } } } - return overwrite_list; + return input; } /** diff --git a/src/units/attack_type.hpp b/src/units/attack_type.hpp index fb1221ad124..4a281015637 100644 --- a/src/units/attack_type.hpp +++ b/src/units/attack_type.hpp @@ -127,14 +127,17 @@ private: // Configured as a bit field, in case that is useful. enum AFFECTS { AFFECT_SELF=1, AFFECT_OTHER=2, AFFECT_EITHER=3 }; - /** overwrite_special_checking : return an unit_ability_list list after checking presence or not of overwrite_specials + /** + * Filter a list of abilities or weapon specials, removing any entries that are overridden by + * the overwrite_specials attributes of a second list. + * * @param ability The special ability type who is being checked. - * @param temp_list the list checked and returned. - * @param abil_list list checked for verify presence of overwrite_specials . - * @param filter_self name of [filter_"self/student"] if is abilities or specials who are checked - * @param is_special for determine if list is a special or a ability. + * @param input list to check, a filtered copy of this list is returned by the function. + * @param overwriters list that may have overwrite_specials attributes. + * @param filter_self name of [filter_"self/student"] if is abilities or specials who are checked. + * @param is_special if true, input contains weapon specials; if false, it contains abilities. */ - unit_ability_list overwrite_special_checking(const std::string& ability, const unit_ability_list& temp_list, const unit_ability_list& abil_list, const std::string& filter_self, bool is_special) const; + unit_ability_list overwrite_special_checking(const std::string& ability, unit_ability_list input, unit_ability_list overwriters, const std::string& filter_self, bool is_special) const; /** check_self_abilities : return an boolean value for checking of activities of abilities used like weapon * @return True if the special @a special is active. * @param cfg the config to one special ability checked.