change calculation rules so that add and sub are always used independently
when two special weapons use multiply and divide with the same id, both operations are used, isn't that so why should it be different with 'add' and 'sub' where it's the larger value that is used (if asub=value_sub and add=value_add are used and value_sub>value_add then value_sub is used). This logic is counter-intuitive. that multiplication/division is applied to (base_value +- add/sub) is understandable but not this discrimination. For me add and sub should still be usable; even if it means changing the rules, but I think we will gain clarity in the end.
This commit is contained in:
parent
686eb30d41
commit
5c9065eb7e
12 changed files with 58 additions and 38 deletions
|
@ -8,7 +8,7 @@
|
|||
# Have the side 1 leader attack the side 2 leader with both its weapons
|
||||
##
|
||||
# Expected end state:
|
||||
# The side 1 leader has 2 weapons each of which now has 3 strikes (5-2), add is ignored
|
||||
# The side 1 leader has 2 weapons each of which now has 4 strikes (5+1-2)
|
||||
#####
|
||||
{COMMON_KEEP_A_B_UNIT_TEST "attacks_add_sub" (
|
||||
[event]
|
||||
|
@ -27,5 +27,5 @@
|
|||
[/modify_unit]
|
||||
[/event]
|
||||
|
||||
{CHECK_STRIKES "3,3" ({SUCCEED})}
|
||||
{CHECK_STRIKES "4,4" ({SUCCEED})}
|
||||
)}
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
# API(s) being tested: [chance_to_hit]value=
|
||||
##
|
||||
# Actions:
|
||||
# Give the leaders a chance_to_hit ability with both the value, add, and sub attributes, adding up to 10 but effectively zero because sub completely overrides the add attribute.
|
||||
# Give the leaders a chance_to_hit ability with both the value, add, and sub attributes.
|
||||
# Give each unit 1000 hp and 100 strikes
|
||||
# Have the side 1 leader attack the side 2 leader with both its weapons
|
||||
##
|
||||
# Expected end state:
|
||||
# the add attributes is ignored
|
||||
# chance to hit is to 0%
|
||||
# The side 1 leader's first weapon strikes 0 times
|
||||
# The side 1 leader's second weapon strikes 0 times
|
||||
#####
|
||||
|
@ -27,7 +27,7 @@
|
|||
[abilities]
|
||||
{TEST_ABILITY attacks 100 () SELF=yes}
|
||||
{TEST_ABILITY chance_to_hit 20 (add=10
|
||||
sub=20) SELF=yes}
|
||||
sub=30) SELF=yes}
|
||||
[/abilities]
|
||||
[/effect]
|
||||
[/modify_unit]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# Have the side 1 leader attack the side 2 leader with both its weapons
|
||||
##
|
||||
# Expected end state:
|
||||
# The side 1 leader has 2 weapons each of which now has 3 damage (5-2), add is ignored
|
||||
# The side 1 leader has 2 weapons each of which now has 4 damage (5+1-2)
|
||||
#####
|
||||
{COMMON_KEEP_A_B_UNIT_TEST "damage_add_sub" (
|
||||
[event]
|
||||
|
@ -26,7 +26,7 @@
|
|||
[/effect]
|
||||
[/modify_unit]
|
||||
|
||||
{ATTACK_AND_VALIDATE 3 (DAMAGE_VALUE=) WEAPON_COUNT=2}
|
||||
{ATTACK_AND_VALIDATE 4 (DAMAGE_VALUE=) WEAPON_COUNT=2}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
) SIDE2_LEADER="Elvish Archer"}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# Have the side 1 leader attack the side 2 leader with both its weapons
|
||||
##
|
||||
# Expected end state:
|
||||
# The both leaders have 2 weapons each of which now drains 3 hp (5-2), add is ignored
|
||||
# The both leaders have 2 weapons each of which now drains 3 hp (5+1-3)
|
||||
# The leader of side 1 heals 3 hp total since it has full hp when its first strike is made
|
||||
# The leader of side 2 heals 6 hp total since it was damaged when its first strike was made
|
||||
#####
|
||||
|
@ -23,7 +23,7 @@
|
|||
apply_to = new_ability
|
||||
[abilities]
|
||||
{TEST_ABILITY drains 5 (add=1
|
||||
sub=2) SELF=yes}
|
||||
sub=3) SELF=yes}
|
||||
[/abilities]
|
||||
[/effect]
|
||||
[/modify_unit]
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
# Have the side 1 leader attack the side 2 leader with both its weapons
|
||||
##
|
||||
# Expected end state:
|
||||
# The both leaders have 2 weapons each of which now heals 3 hp (5-2), add is ignored
|
||||
# The both leaders have 2 weapons each of which now heals 3 hp (5+1-3)
|
||||
# The leader of side 1 heals 3 hp total since it has full hp when its first strike is made
|
||||
# The leader of side 2 heals 6 hp total since it was damaged when its first strike was made
|
||||
#####
|
||||
|
@ -23,7 +23,7 @@
|
|||
apply_to = new_ability
|
||||
[abilities]
|
||||
{TEST_ABILITY heal_on_hit 5 (add=1
|
||||
sub=2) SELF=yes}
|
||||
sub=3) SELF=yes}
|
||||
[/abilities]
|
||||
[/effect]
|
||||
[/modify_unit]
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
# Wait a turn for healing to take place.
|
||||
##
|
||||
# Expected end state:
|
||||
# The Mage has 4 hp: 1 + 2 (rest healing) + 1 ([heals], 3 (value) - 2 (sub))
|
||||
# The value of the add attribute is ignored.
|
||||
# The Mage has 24 hp: 1 + 2 (rest healing) + 21 ([heals], 3 (value) + 20 (add) - 2 (sub))
|
||||
# The value of the add attribute and sub are both used.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "heal_add_sub" (
|
||||
[event]
|
||||
|
@ -55,7 +55,7 @@
|
|||
[/filter]
|
||||
variable = temp
|
||||
[/store_unit]
|
||||
{ASSERT {VARIABLE_CONDITIONAL temp.hitpoints numerical_equals 4}}
|
||||
{ASSERT {VARIABLE_CONDITIONAL temp.hitpoints numerical_equals 24}}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
)}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# API(s) being tested: [illuminates]value=
|
||||
##
|
||||
# Actions:
|
||||
# Give all units 40% self-illuminates bonus damage (50-10), add is ignored
|
||||
# Give all units 60% self-illuminates bonus damage (50+20-10)
|
||||
# Attack each other
|
||||
##
|
||||
# Expected end state:
|
||||
|
@ -27,7 +27,7 @@
|
|||
[/effect]
|
||||
[/modify_unit]
|
||||
|
||||
{ATTACK_AND_VALIDATE 140}
|
||||
{ATTACK_AND_VALIDATE 160}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
) SIDE1_LEADER=Mage SIDE2_LEADER=Mage}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# API(s) being tested: [leadership]value=
|
||||
##
|
||||
# Actions:
|
||||
# Give all units 40% self-leadership bonus damage (50-10), add is ignored
|
||||
# Give all units 60% self-leadership bonus damage (50+20-10), add is ignored
|
||||
# Attack each other
|
||||
##
|
||||
# Expected end state:
|
||||
|
@ -26,7 +26,7 @@
|
|||
[/effect]
|
||||
[/modify_unit]
|
||||
|
||||
{ATTACK_AND_VALIDATE 140}
|
||||
{ATTACK_AND_VALIDATE 160}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
)}
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
# Wait a turn for regenerating to take place.
|
||||
##
|
||||
# Expected end state:
|
||||
# The Mage has 4 hp: 1 + 2 (rest healing) + 1 ([regenerate], 3 (value) - 2 (sub))
|
||||
# The value of the add attribute is ignored.
|
||||
# The Mage has 24 hp: 1 + 2 (rest healing) + 21 ([regenerate], 3 (value) + 20 (add)- 2 (sub))
|
||||
# The value of the add attribute and sub are both used.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST "regenerate_add_sub" (
|
||||
[event]
|
||||
|
@ -52,7 +52,7 @@
|
|||
[/filter]
|
||||
variable = temp
|
||||
[/store_unit]
|
||||
{ASSERT {VARIABLE_CONDITIONAL temp.hitpoints numerical_equals 4}}
|
||||
{ASSERT {VARIABLE_CONDITIONAL temp.hitpoints numerical_equals 24}}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
)}
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
# API(s) being tested: [resistance]value=
|
||||
##
|
||||
# Actions:
|
||||
# Give all units 40% resistance to all damage types (50-10), add is ignored
|
||||
# Give all units 40% resistance to all damage types (50+20-10)
|
||||
# Attack each other
|
||||
##
|
||||
# Expected end state:
|
||||
# The damage from the attack is reduced by 40%
|
||||
# The damage from the attack is reduced by 60%
|
||||
#####
|
||||
{COMMON_KEEP_A_B_UNIT_TEST "resistance_add_sub" (
|
||||
[event]
|
||||
|
@ -27,7 +27,7 @@
|
|||
[/effect]
|
||||
[/modify_unit]
|
||||
|
||||
{ATTACK_AND_VALIDATE 60}
|
||||
{ATTACK_AND_VALIDATE 40}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
)}
|
||||
|
|
|
@ -95,9 +95,9 @@
|
|||
# API(s) being tested: [attacks]sub=
|
||||
##
|
||||
# Expected end state:
|
||||
# Bob's attack has 7 strikes. The difference to add2_add3_cumulative is that sub chooses the lower value, and the order of the abilities determines the order of the calculations.
|
||||
# Bob's attack has 10 strikes. Both the add and the negative sub are used.
|
||||
#####
|
||||
{TWO_CALCULATION_UNIT_TEST add2_sub_minus3_cumulative 5 (cumulative,add=yes,2) (cumulative,sub=yes,-3) 7}
|
||||
{TWO_CALCULATION_UNIT_TEST add2_sub_minus3_cumulative 5 (cumulative,add=yes,2) (cumulative,sub=yes,-3) 10}
|
||||
#####
|
||||
# API(s) being tested: [attacks]sub=,[attacks]cumulative=
|
||||
##
|
||||
|
@ -130,25 +130,36 @@
|
|||
# API(s) being tested: [attacks]add=,[attacks]sub=
|
||||
##
|
||||
# Expected end state:
|
||||
# Bob's attack has 2 strikes. When both add and sub are used in the same [attacks] tag, only the sub is used.
|
||||
# Bob's attack has 4 strikes. When both add and sub are used in the same [attacks] tag, both add and sub are used.
|
||||
#####
|
||||
{ONE_CALCULATION_UNIT_TEST add_sub_combined 5 (add,sub=2,3) 2}
|
||||
{ONE_CALCULATION_UNIT_TEST add_sub_combined 5 (add,sub=2,3) 4}
|
||||
#####
|
||||
# API(s) being tested: [attacks]add=,[attacks]sub=
|
||||
##
|
||||
# Expected end state:
|
||||
# Bob's attack has 2 strikes. In separate [attacks] without separate ids, the order of the abilities determines which one is used.
|
||||
# Bob's attack has 4 strikes.
|
||||
#####
|
||||
{TWO_CALCULATION_UNIT_TEST add_sub_separated 5 (add=2) (sub=3) 2}
|
||||
{TWO_CALCULATION_UNIT_TEST sub_add_separated 5 (sub=2) (add=3) 8}
|
||||
{TWO_CALCULATION_UNIT_TEST add_sub_separated 5 (add=2) (sub=3) 4}
|
||||
# API(s) being tested: [attacks]add=,[attacks]sub=
|
||||
##
|
||||
# Expected end state:
|
||||
# Bob's attack has 6 strikes.
|
||||
#####
|
||||
{TWO_CALCULATION_UNIT_TEST sub_add_separated 5 (sub=2) (add=3) 6}
|
||||
#####
|
||||
# API(s) being tested: [attacks]cumulative=
|
||||
##
|
||||
# Expected end state:
|
||||
# Bob's attack has 2 strikes. These tags don't specify ids, and cumulative doesn't affect add or sub, so the order of the abilities determines which one is used.
|
||||
# Bob's attack has 4 strikes. These tags don't specify ids, and cumulative doesn't affect add or sub.
|
||||
#####
|
||||
{TWO_CALCULATION_UNIT_TEST add_sub_cumulative 5 (cumulative,add=yes,2) (cumulative,sub=yes,3) 2}
|
||||
{TWO_CALCULATION_UNIT_TEST sub_add_cumulative 5 (cumulative,sub=yes,2) (cumulative,add=yes,3) 8}
|
||||
{TWO_CALCULATION_UNIT_TEST add_sub_cumulative 5 (cumulative,add=yes,2) (cumulative,sub=yes,3) 4}
|
||||
#####
|
||||
# API(s) being tested: [attacks]cumulative=
|
||||
##
|
||||
# Expected end state:
|
||||
# Bob's attack has 6 strikes. These tags don't specify ids, and cumulative doesn't affect add or sub.
|
||||
#####
|
||||
{TWO_CALCULATION_UNIT_TEST sub_add_cumulative 5 (cumulative,sub=yes,2) (cumulative,add=yes,3) 6}
|
||||
#####
|
||||
# API(s) being tested: [attacks]id=
|
||||
##
|
||||
|
|
|
@ -2248,6 +2248,7 @@ effect::effect(const unit_ability_list& list, int def, const_attack_ptr att, EFF
|
|||
|
||||
int value_set = (wham == EFFECT_CUMULABLE) ? std::max(list.highest("value").first, 0) + std::min(list.lowest("value").first, 0) : def;
|
||||
std::map<std::string,individual_effect> values_add;
|
||||
std::map<std::string,individual_effect> values_sub;
|
||||
std::map<std::string,individual_effect> values_mul;
|
||||
std::map<std::string,individual_effect> values_div;
|
||||
|
||||
|
@ -2311,9 +2312,9 @@ effect::effect(const unit_ability_list& list, int def, const_attack_ptr att, EFF
|
|||
callable.add("base_value", wfl::variant(def));
|
||||
return formula.evaluate(callable).as_int();
|
||||
});
|
||||
std::map<std::string,individual_effect>::iterator sub_effect = values_add.find(effect_id);
|
||||
if(sub_effect == values_add.end() || sub < sub_effect->second.value) {
|
||||
values_add[effect_id].set(ADD, sub, ability.ability_cfg, ability.teacher_loc);
|
||||
std::map<std::string,individual_effect>::iterator sub_effect = values_sub.find(effect_id);
|
||||
if(sub_effect == values_sub.end() || sub < sub_effect->second.value) {
|
||||
values_sub[effect_id].set(ADD, sub, ability.ability_cfg, ability.teacher_loc);
|
||||
}
|
||||
}
|
||||
if (const config::attribute_value *v = cfg.get("multiply")) {
|
||||
|
@ -2381,7 +2382,15 @@ effect::effect(const unit_ability_list& list, int def, const_attack_ptr att, EFF
|
|||
effect_list_.push_back(val.second);
|
||||
}
|
||||
|
||||
composite_value_ = static_cast<int>((value_set + addition) * multiplier / divisor);
|
||||
/* Additional and subtraction are independent since Wesnoth 1.19.4. Prior to that, they affected each other.
|
||||
*/
|
||||
int substraction = 0;
|
||||
for(const auto& val : values_sub) {
|
||||
substraction += val.second.value;
|
||||
effect_list_.push_back(val.second);
|
||||
}
|
||||
|
||||
composite_value_ = static_cast<int>((value_set + addition + substraction) * multiplier / divisor);
|
||||
//clamp what if min_value < max_value or one attribute only used.
|
||||
if(max_value && min_value && *min_value < *max_value) {
|
||||
composite_value_ = std::clamp(*min_value, *max_value, composite_value_);
|
||||
|
|
Loading…
Add table
Reference in a new issue