Skip to content

Commit

Permalink
add filter_attacker and filter_defender to abilities
Browse files Browse the repository at this point in the history
To complete the resemblance to the real weapon specials, I add these two tags

Closes #3743
  • Loading branch information
CelticMinstrel committed Dec 2, 2018
1 parent dbb2228 commit 16927f9
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 15 deletions.
52 changes: 40 additions & 12 deletions src/actions/attack.cpp
Expand Up @@ -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()) {
Expand All @@ -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()) {
Expand All @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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};
Expand Down
4 changes: 2 additions & 2 deletions src/actions/attack.hpp
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/units/unit.hpp
Expand Up @@ -1610,7 +1610,7 @@ class unit
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:
/**
Expand Down

0 comments on commit 16927f9

Please sign in to comment.