add filter_attacker and filter_defender to abilities

To complete the resemblance to the real weapon specials, I add these two tags

Closes #3743
This commit is contained in:
Celtic Minstrel 2018-12-01 20:45:22 -05:00
parent dbb222813c
commit 16927f9508
3 changed files with 43 additions and 15 deletions

View file

@ -1587,16 +1587,30 @@ bool unit::abilities_filter_matches(const config& cfg, bool attacker, int res) c
//functions for emulate weapon specials.
//filter opponent and affect self/opponent/both option.
bool unit::ability_filter_opponent(const std::string& ability,const config& cfg,const map_location& loc) const
bool unit::ability_filter_fighter(const std::string& ability, const std::string& filter_attacker , const config& cfg, const map_location& loc) const
{
const config &filter = cfg.child("filter_opponent");
const config &filter = cfg.child(filter_attacker);
if(!filter) {
return true;
}
return unit_filter(vconfig(filter)).set_use_flat_tod(ability == "illuminates").matches(*this, loc);
}
bool leadership_affects_self(const std::string& ability,const unit_map& units, const map_location& loc, const_attack_ptr weapon,const_attack_ptr opp_weapon)
static bool ability_apply_filter(const unit_map::const_iterator un,const unit_map::const_iterator up,const std::string& ability,const config& cfg, const unit_map& units, const map_location& loc, const map_location& opp_loc, bool attacker )
{
if(!up->ability_filter_fighter(ability, "filter_opponent", cfg, opp_loc)){
return true;
}
if((attacker && !un->ability_filter_fighter(ability, "filter_attacker", cfg, loc)) || (!attacker && !up->ability_filter_fighter(ability, "filter_attacker", cfg, opp_loc))){
return true;
}
if((!attacker && !un->ability_filter_fighter(ability, "filter_defender", cfg, loc)) || (attacker && !up->ability_filter_fighter(ability, "filter_defender", cfg, opp_loc))){
return true;
}
return false;
}
bool leadership_affects_self(const std::string& ability,const unit_map& units, const map_location& loc, bool attacker, const_attack_ptr weapon,const_attack_ptr opp_weapon)
{
const unit_map::const_iterator un = units.find(loc);
if(un == units.end()) {
@ -1609,12 +1623,18 @@ bool leadership_affects_self(const std::string& ability,const unit_map& units, c
if(apply_to.empty() || apply_to == "both" || apply_to == "self") {
return true;
}
if(attacker && apply_to == "attacker") {
return true;
}
if(!attacker && apply_to == "defender") {
return true;
}
++i;
}
return false;
}
bool leadership_affects_opponent(const std::string& ability,const unit_map& units, const map_location& loc, const_attack_ptr weapon,const_attack_ptr opp_weapon)
bool leadership_affects_opponent(const std::string& ability,const unit_map& units, const map_location& loc, bool attacker, const_attack_ptr weapon,const_attack_ptr opp_weapon)
{
const unit_map::const_iterator un = units.find(loc);
if(un == units.end()) {
@ -1627,6 +1647,12 @@ bool leadership_affects_opponent(const std::string& ability,const unit_map& unit
if(apply_to == "both" || apply_to == "opponent") {
return true;
}
if(attacker && apply_to == "defender") {
return true;
}
if(!attacker && apply_to == "attacker") {
return true;
}
++i;
}
return false;
@ -1644,13 +1670,15 @@ std::pair<int, bool> ability_leadership(const std::string& ability,const unit_ma
unit_ability_list abil = un->get_abilities(ability, weapon, opp_weapon);
for(unit_ability_list::iterator i = abil.begin(); i != abil.end();) {
const config &filter = (*i->first).child("filter_opponent");
const config &filter_attacker = (*i->first).child("filter_attacker");
const config &filter_defender = (*i->first).child("filter_defender");
bool show_result = false;
if(up == units.end() && !filter) {
if(up == units.end() && !filter && !filter_attacker && !filter_defender) {
show_result = un->abilities_filter_matches(*i->first, attacker, abil_value);
} else if(up == units.end() && filter) {
} else if(up == units.end() && (filter || filter_attacker || filter_defender)) {
return {abil_value, false};
} else {
show_result = !(!un->abilities_filter_matches(*i->first, attacker, abil_value) || !up->ability_filter_opponent(ability, *i->first, opp_loc));
show_result = !(!un->abilities_filter_matches(*i->first, attacker, abil_value) || ability_apply_filter(un, up, ability, *i->first, units, loc, opp_loc, attacker));
}
if(!show_result) {
@ -1679,7 +1707,7 @@ bool bool_leadership(const std::string& ability,const unit_map& units, const map
unit_ability_list abil = un->get_abilities(ability, weapon, opp_weapon);
for(unit_ability_list::iterator i = abil.begin(); i != abil.end();) {
const std::string& active_on = (*i->first)["active_on"];
if(!(active_on.empty() || (attacker && active_on == "offense") || (!attacker && active_on == "defense")) || !up->ability_filter_opponent(ability, *i->first, opp_loc)) {
if(!(active_on.empty() || (attacker && active_on == "offense") || (!attacker && active_on == "defense")) || ability_apply_filter(un, up, ability, *i->first, units, loc, opp_loc, attacker)) {
i = abil.erase(i);
} else {
++i;
@ -1697,11 +1725,11 @@ bool attack_type::bool_ability(const std::string& ability) const
bool abil_bool= get_special_bool(ability);
const unit_map& units = display::get_singleton()->get_units();
if(leadership_affects_self(ability, units, self_loc_, shared_from_this(), other_attack_)) {
if(leadership_affects_self(ability, units, self_loc_, is_attacker_, shared_from_this(), other_attack_)) {
abil_bool = get_special_bool(ability) || bool_leadership(ability, units, self_loc_, other_loc_, is_attacker_, shared_from_this(), other_attack_);
}
if(leadership_affects_opponent(ability, units, other_loc_, other_attack_, shared_from_this())) {
if(leadership_affects_opponent(ability, units, other_loc_, !is_attacker_, other_attack_, shared_from_this())) {
abil_bool = get_special_bool(ability) || bool_leadership(ability, units, other_loc_, self_loc_, !is_attacker_, other_attack_, shared_from_this());
}
return abil_bool;
@ -1712,11 +1740,11 @@ std::pair<int, bool> attack_type::combat_ability(const std::string& ability, int
{
const unit_map& units = display::get_singleton()->get_units();
if(leadership_affects_self(ability, units, self_loc_, shared_from_this(), other_attack_)) {
if(leadership_affects_self(ability, units, self_loc_, is_attacker_, shared_from_this(), other_attack_)) {
return ability_leadership(ability, units, self_loc_, other_loc_, is_attacker_, abil_value, backstab_pos, shared_from_this(), other_attack_);
}
if(leadership_affects_opponent(ability, units, other_loc_, other_attack_, shared_from_this())) {
if(leadership_affects_opponent(ability, units, other_loc_, !is_attacker_, other_attack_, shared_from_this())) {
return ability_leadership(ability, units, other_loc_,self_loc_, !is_attacker_, abil_value, backstab_pos, other_attack_, shared_from_this());
}
return {abil_value, false};

View file

@ -279,8 +279,8 @@ void attack_unit_and_advance(const map_location& attacker,
* Returns the bonus percentage (possibly 0 if there's no leader adjacent).
*/
int under_leadership(const unit &u, const map_location& loc, const_attack_ptr weapon, const_attack_ptr opp_weapon = nullptr);
bool leadership_affects_self(const std::string& ability,const unit_map& units, const map_location& loc, const_attack_ptr weapon=nullptr,const_attack_ptr opp_weapon=nullptr);
bool leadership_affects_opponent(const std::string& ability,const unit_map& units, const map_location& loc, const_attack_ptr weapon=nullptr,const_attack_ptr opp_weapon=nullptr);
bool leadership_affects_self(const std::string& ability,const unit_map& units, const map_location& loc, bool attacker=true, const_attack_ptr weapon=nullptr,const_attack_ptr opp_weapon=nullptr);
bool leadership_affects_opponent(const std::string& ability,const unit_map& units, const map_location& loc, bool attacker=true, const_attack_ptr weapon=nullptr,const_attack_ptr opp_weapon=nullptr);
std::pair<int, bool> ability_leadership(const std::string& ability, const unit_map& units, const map_location& loc, const map_location& opp_loc, bool attacker=true, int abil_value=0, bool backstab_pos=false, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr);
bool bool_leadership(const std::string& ability,const unit_map& units, const map_location& loc, const map_location& opp_loc, bool attacker=true, const_attack_ptr weapon=nullptr, const_attack_ptr opp_weapon=nullptr);

View file

@ -1610,7 +1610,7 @@ public:
void remove_ability_by_id(const std::string& ability);
bool abilities_filter_matches(const config& cfg, bool attacker, int res) const;
bool ability_filter_opponent(const std::string& ability,const config& cfg,const map_location& loc) const;
bool ability_filter_fighter(const std::string& ability, const std::string& filter_attacker , const config& cfg,const map_location& loc) const;
private:
/**