Add overwrite_specials attribute to allow forcing a lower chance to hit

The reported issue being that the FORCE_CHANCE_TO_HIT macro was able to force an increase in an attack's chance to hit, but no longer able to force a decrease.
This commit is contained in:
newfrenchy83 2020-12-14 21:57:59 +01:00 committed by GitHub
parent 3d7f0a6116
commit 2168f629fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 152 additions and 2 deletions

View File

@ -22,6 +22,7 @@
* Text labels now use the hyperlink mouse cursor while hovering links.
* Link awareness is now configured on a per-instance basis for labels/scroll labels instead of globally in their definition.
### WML Engine
* Add a overwrite_specials option for abilities like weapon could overwrite specials or other ablities like weapon
### Miscellaneous and Bug Fixes
* Fixed several possible crashes in wmllint

View File

@ -554,6 +554,7 @@
value={CTH_NUMBER}
cumulative=no
affect_self=yes
overwrite_specials=yes
[filter_opponent]
{SECOND_FILTER}
[/filter_opponent]
@ -606,6 +607,7 @@
value={CTH_NUMBER}
cumulative=no
affect_self=yes
overwrite_specials=yes
[filter_opponent]
{SECOND_FILTER}
[/filter_opponent]

View File

@ -5,6 +5,7 @@
max=infinite
super="units/unit_type/abilities/~generic~,units/unit_type/attack/specials/" + {NAME}
{FILTER_TAG "filter_student" unit {FILTER_TAG "filter_weapon" weapon ()}}
{SIMPLE_KEY overwrite_specials bool}
[/tag]
#enddef

View File

@ -0,0 +1,118 @@
# This unit test defines a WML object based implementation of the "unupgradable" ability
# https://github.com/ProditorMagnus/Ageless-for-1-14/blob/52c1eaf31722bb58046a1b459d4f29daa8d88487/data/general_data/weapon_specials/unupgradable.cfg
# and checks that it works. What is being tested here is that
# FORCE_CHANCE_TO_HIT macro must doing misses all attacks then what [chance_to_hit] value equals 100%
# - through [attacks]
# - through [effect] increase_attacks
{GENERIC_UNIT_TEST "test_force_chance_to_hit_macro" (
{FORCE_CHANCE_TO_HIT (id=bob) (id=alice) 0 ()}
{FORCE_CHANCE_TO_HIT (id=alice) (id=bob) 0 ()}
[event]
name=start
[modify_unit]
[filter]
[/filter]
max_hitpoints=100
hitpoints=100
attacks_left=1
[/modify_unit]
[object]
silent=yes
[effect]
apply_to=attack
[set_specials]
mode=append
[attacks]
value=10
[/attacks]
[attacks]
add=13
[/attacks]
[damage]
value=1
[/damage]
[chance_to_hit]
value=100
[/chance_to_hit]
[/set_specials]
[/effect]
[filter]
id=bob
[/filter]
[/object]
[object]
silent=yes
[effect]
apply_to=attack
[set_specials]
mode=append
[attacks]
value=10
[/attacks]
[damage]
value=1
[/damage]
[chance_to_hit]
value=100
[/chance_to_hit]
[/set_specials]
[/effect]
[filter]
id=alice
[/filter]
[/object]
[store_unit]
[filter]
id=alice
[/filter]
variable=a
kill=yes
[/store_unit]
[store_unit]
[filter]
id=bob
[/filter]
variable=b
[/store_unit]
[unstore_unit]
variable=a
find_vacant=yes
x,y=$b.x,$b.y
[/unstore_unit]
[store_unit]
[filter]
id=alice
[/filter]
variable=a
[/store_unit]
[do_command]
[attack]
weapon=0
defender_weapon=0
[source]
x,y=$a.x,$a.y
[/source]
[destination]
x,y=$b.x,$b.y
[/destination]
[/attack]
[/do_command]
[store_unit]
[filter]
id=alice
[/filter]
variable=a
[/store_unit]
[store_unit]
[filter]
id=bob
[/filter]
variable=b
[/store_unit]
{ASSERT ({VARIABLE_CONDITIONAL a.hitpoints equals 100})}
{ASSERT ({VARIABLE_CONDITIONAL b.hitpoints equals 100})}
{SUCCEED}
[/event]
)}

View File

@ -1117,23 +1117,44 @@ unit_ability_list attack_type::list_ability(const std::string& ability) const
if(self_) {
abil_list.append((*self_).get_abilities(ability, self_loc_));
for(unit_ability_list::iterator i = abil_list.begin(); i != abil_list.end();) {
if(!special_active(*i->ability_cfg, AFFECT_SELF, ability, true, "filter_student")) {
if(!((*i->ability_cfg)["overwrite_specials"].to_bool() && special_active(*i->ability_cfg, AFFECT_SELF, ability, true, "filter_student"))) {
i = abil_list.erase(i);
} else {
++i;
}
}
if(abil_list.empty()){
abil_list.append((*self_).get_abilities(ability, self_loc_));
for(unit_ability_list::iterator i = abil_list.begin(); i != abil_list.end();) {
if(!special_active(*i->ability_cfg, AFFECT_SELF, ability, true, "filter_student")) {
i = abil_list.erase(i);
} else {
++i;
}
}
}
}
if(other_) {
abil_other_list.append((*other_).get_abilities(ability, other_loc_));
for(unit_ability_list::iterator i = abil_other_list.begin(); i != abil_other_list.end();) {
if(!special_active_impl(other_attack_, shared_from_this(), *i->ability_cfg, AFFECT_OTHER, ability, true, "filter_student")) {
if(!((*i->ability_cfg)["overwrite_specials"].to_bool() && special_active_impl(other_attack_, shared_from_this(), *i->ability_cfg, AFFECT_OTHER, ability, true, "filter_student"))) {
i = abil_other_list.erase(i);
} else {
++i;
}
}
if(abil_other_list.empty()){
abil_other_list.append((*other_).get_abilities(ability, other_loc_));
for(unit_ability_list::iterator i = abil_other_list.begin(); i != abil_other_list.end();) {
if(!special_active_impl(other_attack_, shared_from_this(), *i->ability_cfg, AFFECT_OTHER, ability, true, "filter_student")) {
i = abil_other_list.erase(i);
} else {
++i;
}
}
}
}
abil_list.append(abil_other_list);
return abil_list;
@ -1142,6 +1163,12 @@ unit_ability_list attack_type::list_ability(const std::string& ability) const
unit_ability_list attack_type::get_special_ability(const std::string& ability) const
{
unit_ability_list abil_list = list_ability(ability);
for(unit_ability_list::iterator i = abil_list.begin(); i != abil_list.end();) {
if((*i->ability_cfg)["overwrite_specials"].to_bool()) {
return abil_list;
}
++i;
}
abil_list.append(get_specials(ability));
return abil_list;
}

View File

@ -167,6 +167,7 @@
0 feeding
0 swarm_disables_upgrades
0 swarm_disables_upgrades_with_abilities
0 test_force_chance_to_hit_macro
#
# Deterministic unit facing tests
0 recruit_facing_enemy_one