fix cumulative=yes don't function for [leadership]

Fix https://github.com/wesnoth/wesnoth/issues/6466 issue.
This commit is contained in:
newfrenchy83 2022-01-28 15:10:52 +01:00 committed by Pentarctagon
parent 81d41a861d
commit fcd0c02c8d
4 changed files with 50 additions and 24 deletions

View file

@ -221,13 +221,13 @@ battle_context_unit_stats::battle_context_unit_stats(nonempty_unit_const_ptr up,
if(drains) {
unit_ability_list drain_specials = weapon->get_specials_and_abilities("drains");
// Compute the drain percent (with 50% as the base for backward compatibility)
unit_abilities::effect drain_percent_effects(drain_specials, 50, backstab_pos, weapon);
unit_abilities::effect drain_percent_effects(drain_specials, 50, backstab_pos, weapon, true);
drain_percent = drain_percent_effects.get_composite_value();
}
// Add heal_on_hit (the drain constant)
unit_ability_list heal_on_hit_specials = weapon->get_specials_and_abilities("heal_on_hit");
unit_abilities::effect heal_on_hit_effects(heal_on_hit_specials, 0, backstab_pos, weapon);
unit_abilities::effect heal_on_hit_effects(heal_on_hit_specials, 0, backstab_pos, weapon, true);
drain_constant += heal_on_hit_effects.get_composite_value();
drains = drain_constant || drain_percent;
@ -344,13 +344,13 @@ battle_context_unit_stats::battle_context_unit_stats(const unit_type* u_type,
unit_ability_list drain_specials = weapon->get_specials("drains");
// Compute the drain percent (with 50% as the base for backward compatibility)
unit_abilities::effect drain_percent_effects(drain_specials, 50, backstab_pos, weapon);
unit_abilities::effect drain_percent_effects(drain_specials, 50, backstab_pos, weapon, true);
drain_percent = drain_percent_effects.get_composite_value();
}
// Add heal_on_hit (the drain constant)
unit_ability_list heal_on_hit_specials = weapon->get_specials("heal_on_hit");
unit_abilities::effect heal_on_hit_effects(heal_on_hit_specials, 0, backstab_pos, weapon);
unit_abilities::effect heal_on_hit_effects(heal_on_hit_specials, 0, backstab_pos, weapon, true);
drain_constant += heal_on_hit_effects.get_composite_value();
drains = drain_constant || drain_percent;
@ -1586,7 +1586,7 @@ void attack_unit_and_advance(const map_location& attacker,
int under_leadership(const unit &u, const map_location& loc, const_attack_ptr weapon, const_attack_ptr opp_weapon)
{
unit_ability_list abil = u.get_abilities_weapons("leadership", loc, weapon, opp_weapon);
unit_abilities::effect leader_effect(abil, 0, false);
unit_abilities::effect leader_effect(abil, 0, false, nullptr, true);
return leader_effect.get_composite_value();
}

View file

@ -193,7 +193,7 @@ namespace {
// Regeneration?
unit_ability_list regen_list = patient.get_abilities("regenerate");
unit_abilities::effect regen_effect(regen_list, 0, false);
unit_abilities::effect regen_effect(regen_list, 0, false, nullptr, true);
update_healing(healing, harming, regen_effect.get_composite_value());
}
@ -212,7 +212,7 @@ namespace {
}
// Now we can get the aggregate healing amount.
unit_abilities::effect heal_effect(heal_list, 0, false);
unit_abilities::effect heal_effect(heal_list, 0, false, nullptr, true);
if ( update_healing(healing, harming, heal_effect.get_composite_value()) )
{
// Collect the healers involved.

View file

@ -1742,7 +1742,7 @@ bool filter_base_matches(const config& cfg, int def)
return true;
}
effect::effect(const unit_ability_list& list, int def, bool backstab, const_attack_ptr att) :
effect::effect(const unit_ability_list& list, int def, bool backstab, const_attack_ptr att, bool is_cumulable) :
effect_list_(),
composite_value_(0)
{
@ -1768,24 +1768,50 @@ effect::effect(const unit_ability_list& list, int def, bool backstab, const_atta
if (!filter_base_matches(cfg, def))
continue;
if (const config::attribute_value *v = cfg.get("value")) {
int value = get_single_ability_value(*v, def, ability, list.loc(), att, [&](const wfl::formula& formula, wfl::map_formula_callable& callable) {
callable.add("base_value", wfl::variant(def));
return formula.evaluate(callable).as_int();
});
if(!is_cumulable || !cfg["cumulative"].to_bool()){
if (const config::attribute_value *v = cfg.get("value")) {
int value = get_single_ability_value(*v, def, ability, list.loc(), att, [&](const wfl::formula& formula, wfl::map_formula_callable& callable) {
callable.add("base_value", wfl::variant(def));
return formula.evaluate(callable).as_int();
});
int value_cum = cfg["cumulative"].to_bool() ? std::max(def, value) : value;
assert((set_effect_min.type != NOT_USED) == (set_effect_max.type != NOT_USED));
if(set_effect_min.type == NOT_USED) {
set_effect_min.set(SET, value_cum, ability.ability_cfg, ability.teacher_loc);
set_effect_max.set(SET, value_cum, ability.ability_cfg, ability.teacher_loc);
}
else {
if(value_cum > set_effect_max.value) {
int value_cum = cfg["cumulative"].to_bool() ? std::max(def, value) : value;
assert((set_effect_min.type != NOT_USED) == (set_effect_max.type != NOT_USED));
if(set_effect_min.type == NOT_USED) {
set_effect_min.set(SET, value_cum, ability.ability_cfg, ability.teacher_loc);
set_effect_max.set(SET, value_cum, ability.ability_cfg, ability.teacher_loc);
}
if(value_cum < set_effect_min.value) {
set_effect_min.set(SET, value_cum, ability.ability_cfg, ability.teacher_loc);
else {
if(value_cum > set_effect_max.value) {
set_effect_max.set(SET, value_cum, ability.ability_cfg, ability.teacher_loc);
}
if(value_cum < set_effect_min.value) {
set_effect_min.set(SET, value_cum, ability.ability_cfg, ability.teacher_loc);
}
}
}
} else {
if (const config::attribute_value *v = cfg.get("value")) {
int value = get_single_ability_value(*v, def, ability, list.loc(), att, [&](const wfl::formula& formula, wfl::map_formula_callable& callable) {
callable.add("base_value", wfl::variant(def));
return formula.evaluate(callable).as_int();
});
std::map<std::string,individual_effect>::iterator value_effect = values_add.find(effect_id);
if(value>=0){
if(value_effect == values_add.end() || (value > value_effect->second.value && value_effect->second.value>=0)) {
values_add[effect_id].set(ADD, value, ability.ability_cfg, ability.teacher_loc);
}
else if(value_effect == values_add.end() || (value > value_effect->second.value && value_effect->second.value<0)) {
values_add[effect_id].set(ADD, (value+value_effect->second.value), ability.ability_cfg, ability.teacher_loc);
}
}
else {
if(value_effect == values_add.end() || (value < value_effect->second.value && value_effect->second.value<=0)) {
values_add[effect_id].set(ADD, value, ability.ability_cfg, ability.teacher_loc);
}
else if(value_effect == values_add.end() || (value < value_effect->second.value && value_effect->second.value>0)) {
values_add[effect_id].set(ADD, (value+value_effect->second.value), ability.ability_cfg, ability.teacher_loc);
}
}
}
}

View file

@ -39,7 +39,7 @@ struct individual_effect
class effect
{
public:
effect(const unit_ability_list& list, int def, bool backstab, const_attack_ptr attacker = const_attack_ptr());
effect(const unit_ability_list& list, int def, bool backstab, const_attack_ptr attacker = const_attack_ptr(), bool is_cumulable=false);
// Provide read-only access to the effect list:
typedef std::vector<individual_effect>::const_iterator iterator;
typedef std::vector<individual_effect>::const_iterator const_iterator;