From c7de7ce9d428ed82f67a157b92b97cfd5608f54c Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Sun, 6 Mar 2016 18:28:23 -0500 Subject: [PATCH] Fix backstab always showing augmented damage in sidebar Until now, [damage] (and possibly other) specials which relied on filters involving the opponent would display in the sidebar as if the augmentation were always active (though when attacking, it worked correctly). This is now fixed - such specials never show the augmentation in the sidebar now. In addition, some minor code cleanup (initializing the weapon special adjacency filters outside the loop). --- src/reports.cpp | 1 + src/unit_abilities.cpp | 39 ++++++++++++++++++++++++++++++--------- src/unit_attack_type.hpp | 2 ++ 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/reports.cpp b/src/reports.cpp index dc132a31848f..55dcb2744b05 100644 --- a/src/reports.cpp +++ b/src/reports.cpp @@ -802,6 +802,7 @@ static int attack_info(reports::context & rc, const attack_type &at, config &res add_text(res, flush(str), flush(tooltip)); } + at.set_specials_context_for_listing(); std::vector active; const std::vector > &specials = at.special_tooltips(&active); const size_t specials_size = specials.size(); diff --git a/src/unit_abilities.cpp b/src/unit_abilities.cpp index ece4ba461abc..a33a2f9aee5f 100644 --- a/src/unit_abilities.cpp +++ b/src/unit_abilities.cpp @@ -685,6 +685,7 @@ void attack_type::set_specials_context(const map_location& unit_loc, other_loc_ = other_loc; is_attacker_ = attacking; other_attack_ = other_attack; + is_for_listing_ = false; } /** @@ -699,6 +700,12 @@ void attack_type::set_specials_context(const map_location& loc, bool attacking) other_loc_ = map_location::null_location(); is_attacker_ = attacking; other_attack_ = NULL; + is_for_listing_ = false; +} + +void attack_type::set_specials_context_for_listing() const +{ + is_for_listing_ = true; } @@ -803,9 +810,10 @@ namespace { // Helpers for attack_type::special_active() const map_location & loc, const attack_type * weapon, const config & filter, + const bool for_listing, const std::string & child_tag) { - if (!loc.valid() || !u2.valid()) + if (for_listing && !loc.valid()) // The special's context was set to ignore this unit, so assume we pass. // (This is used by reports.cpp to show active specials when the // opponent is not known. From a player's perspective, the special @@ -817,10 +825,23 @@ namespace { // Helpers for attack_type::special_active() if ( !filter_child ) // The special does not filter on this unit, so we pass. return true; + + // If the primary unit doesn't exist, there's nothing to match + if (!un_it.valid()) { + return false; + } + + unit_filter ufilt(vconfig(filter_child), resources::filter_con); + + // If the other unit doesn't exist, try matching without it + if (!u2.valid()) { + return ufilt.matches(*un_it, loc); + } // Check for a unit match. - if ( !un_it.valid() || !unit_filter(vconfig(filter_child), resources::filter_con).matches(*un_it, loc, *u2)) + if (!ufilt.matches(*un_it, loc, *u2)) { return false; + } // Check for a weapon match. if ( const config & filter_weapon = filter_child.child("filter_weapon") ) { @@ -890,13 +911,13 @@ bool attack_type::special_active(const config& special, AFFECTS whom, const attack_type * def_weapon = is_attacker_ ? other_attack_ : this; // Filter the units involved. - if (!special_unit_matches(self, other, self_loc_, this, special, "filter_self")) + if (!special_unit_matches(self, other, self_loc_, this, special, is_for_listing_, "filter_self")) return false; - if (!special_unit_matches(other, self, other_loc_, other_attack_, special, "filter_opponent")) + if (!special_unit_matches(other, self, other_loc_, other_attack_, special, is_for_listing_, "filter_opponent")) return false; - if (!special_unit_matches(att, def, att_loc, att_weapon, special, "filter_attacker")) + if (!special_unit_matches(att, def, att_loc, att_weapon, special, is_for_listing_, "filter_attacker")) return false; - if (!special_unit_matches(def, att, def_loc, def_weapon, special, "filter_defender")) + if (!special_unit_matches(def, att, def_loc, def_weapon, special, is_for_listing_, "filter_defender")) return false; map_location adjacent[6]; @@ -907,13 +928,13 @@ bool attack_type::special_active(const config& special, AFFECTS whom, { size_t count = 0; std::vector dirs = map_location::parse_directions(i["adjacent"]); + unit_filter filter(vconfig(i), resources::filter_con); BOOST_FOREACH(const map_location::DIRECTION index, dirs) { if (index == map_location::NDIRECTIONS) continue; unit_map::const_iterator unit = units.find(adjacent[index]); - if ( unit == units.end() || - !unit_filter(vconfig(i), resources::filter_con).matches(*unit, adjacent[index], *self)) //TODO: Should this filter get precomputed? + if (unit == units.end() || !filter.matches(*unit, adjacent[index], *self)) return false; if (i.has_attribute("is_enemy")) { const display_context& dc = resources::filter_con->get_disp_context(); @@ -936,11 +957,11 @@ bool attack_type::special_active(const config& special, AFFECTS whom, { size_t count = 0; std::vector dirs = map_location::parse_directions(i["adjacent"]); + terrain_filter adj_filter(vconfig(i), resources::filter_con); BOOST_FOREACH(const map_location::DIRECTION index, dirs) { if (index == map_location::NDIRECTIONS) continue; - terrain_filter adj_filter(vconfig(i), resources::filter_con); if(!adj_filter.match(adjacent[index])) { return false; } diff --git a/src/unit_attack_type.hpp b/src/unit_attack_type.hpp index 2fe734bd61c2..15fa53b080a7 100644 --- a/src/unit_attack_type.hpp +++ b/src/unit_attack_type.hpp @@ -73,6 +73,7 @@ class attack_type void set_specials_context(const map_location& unit_loc, const map_location& other_loc, bool attacking, const attack_type *other_attack) const; void set_specials_context(const map_location& loc, bool attacking = true) const; + void set_specials_context_for_listing() const; /// Calculates the number of attacks this weapon has, considering specials. void modified_attacks(bool is_backstab, unsigned & min_attacks, @@ -105,6 +106,7 @@ class attack_type mutable map_location self_loc_, other_loc_; mutable bool is_attacker_; mutable const attack_type* other_attack_; + mutable bool is_for_listing_; t_string description_; std::string id_;