Fix #3811 negative value in heals ability

When multiple negative heal abilities are present, the game now
chooses the ability with the lowest value. The leadership ability
now also uses the same get_composite_value function that is also
used by most other abilities
This commit is contained in:
newfrenchy83 2019-01-02 20:29:52 +01:00 committed by gfgtdf
parent 4384bd550a
commit 7114174789
4 changed files with 77 additions and 18 deletions

View file

@ -870,10 +870,60 @@ Xu, Xu, Qxu, Qxu, Ql, Ql, Ql, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Xu, Gg, Gg, Gg, Gg, Gg
[/modifications]
[/unit]
[unit]
# Drain tester (for undead and default drain)
# Drain tester (for undead and default drain) and reverse heals tester
x,y=21,7
type="Lich"
generate_name=yes
[modifications]
[object]
[effect]
apply_to=new_ability
[abilities]
[heals]
value=-4
id=aura of death 4
affect_enemies=yes
name= _ "aura of seath ("4")"
female_name= _ "female^aura of death ("4")"
affect_self=no
affect_allies=no
poison=slowed
[affect_adjacent]
adjacent=n,ne,se,s,sw,n
[/affect_adjacent]
[/heals]
[/abilities]
[/effect]
[/object]
[/modifications]
[/unit]
[unit]
# reverse heals tester
x,y=20,6
type="Ancient Lich"
generate_name=yes
[modifications]
[object]
[effect]
apply_to=new_ability
[abilities]
[heals]
value=-8
id=aura of death 8
affect_enemies=yes
name= _ "aura of seath ("8")"
female_name= _ "female^aura of death ("8")"
affect_self=no
affect_allies=no
poison=slowed
[affect_adjacent]
adjacent=n,ne,se,s,sw,n
[/affect_adjacent]
[/heals]
[/abilities]
[/effect]
[/object]
[/modifications]
[/unit]
[unit]
# Drain tester

View file

@ -35,6 +35,8 @@
max=infinite
super="units/unit_type/abilities/~generic~"
{SIMPLE_KEY value f_int}
{SIMPLE_KEY add f_int}
{SIMPLE_KEY sub f_int}
{SIMPLE_KEY poison string} # TODO: Enum
[/tag]
[tag]

View file

@ -1567,9 +1567,8 @@ 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("leadership", loc, weapon, opp_weapon);
int leader_up = std::max(0, abil.highest("value").first);
int leader_down = std::min(0, abil.lowest("value").first);
return leader_up + leader_down;
unit_abilities::effect leader_effect(abil, 0, false);
return leader_effect.get_composite_value();
}
//begin of weapon emulates function.

View file

@ -1159,12 +1159,12 @@ effect::effect(const unit_ability_list& list, int def, bool backstab) :
{
int value_set = def;
bool value_is_set = false;
std::map<std::string,individual_effect> values_add;
std::map<std::string,individual_effect> values_mul;
std::map<std::string,individual_effect> values_div;
individual_effect set_effect;
individual_effect set_effect_max;
individual_effect set_effect_min;
for (const unit_ability & ability : list) {
const config& cfg = *ability.first;
@ -1185,18 +1185,20 @@ effect::effect(const unit_ability_list& list, int def, bool backstab) :
return formula.evaluate(callable).as_int();
});
bool cumulative = cfg["cumulative"].to_bool();
if (!value_is_set && !cumulative) {
value_set = value;
set_effect.set(SET, value, ability.first, ability.second);
} else {
if (cumulative) value_set = std::max<int>(value_set, def);
if (value > value_set) {
value_set = value;
set_effect.set(SET, value, ability.first, ability.second);
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.first, ability.second);
set_effect_max.set(SET, value_cum, ability.first, ability.second);
}
else {
if(value_cum > set_effect_max.value) {
set_effect_max.set(SET, value_cum, ability.first, ability.second);
}
if(value_cum < set_effect_min.value) {
set_effect_min.set(SET, value_cum, ability.first, ability.second);
}
}
value_is_set = true;
}
if (const config::attribute_value *v = cfg.get("add")) {
@ -1247,8 +1249,14 @@ effect::effect(const unit_ability_list& list, int def, bool backstab) :
}
}
if(value_is_set && set_effect.type != NOT_USED) {
effect_list_.push_back(set_effect);
if(set_effect_max.type != NOT_USED) {
value_set = std::max(set_effect_max.value, 0) + std::min(set_effect_min.value, 0);
if(set_effect_max.value > def) {
effect_list_.push_back(set_effect_max);
}
if(set_effect_min.value < def) {
effect_list_.push_back(set_effect_min);
}
}
/* Do multiplication with floating point values rather than integers