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).
This commit is contained in:
Celtic Minstrel 2016-03-06 18:28:23 -05:00
parent c761a80bd5
commit c7de7ce9d4
3 changed files with 33 additions and 9 deletions

View file

@ -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<bool> active;
const std::vector<std::pair<t_string, t_string> > &specials = at.special_tooltips(&active);
const size_t specials_size = specials.size();

View file

@ -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<map_location::DIRECTION> 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<map_location::DIRECTION> 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;
}

View file

@ -73,6 +73,7 @@ public:
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 @@ private:
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_;