Add an 'alignment' attribute to attacks
This attribute, when set to a valid value of lawful|neutral|chaotic|liminal, will assign to the weapon a different alignment than the unit alignment used by default. This alignment is then used when attacking with this weapon. The attribute is not accessible from lua so far since the fallback to unit alignment does not work.
This commit is contained in:
parent
363241faf9
commit
feef53d4ab
14 changed files with 324 additions and 5 deletions
|
@ -0,0 +1,2 @@
|
|||
### WML Engine
|
||||
* Add alignment in [attack] to specify the alignment of an attack independent of the unit's alignment.
|
|
@ -3,6 +3,7 @@
|
|||
name="$filter_weapon"
|
||||
max=0
|
||||
{SIMPLE_KEY range string_list}
|
||||
{SIMPLE_KEY alignment alignment}
|
||||
{SIMPLE_KEY name string_list}
|
||||
{SIMPLE_KEY type string_list}
|
||||
{SIMPLE_KEY special string_list}
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
{SIMPLE_KEY set_type string}
|
||||
{SIMPLE_KEY set_icon string}
|
||||
{SIMPLE_KEY set_range string}
|
||||
|
||||
{SIMPLE_KEY set_alignment string}
|
||||
|
||||
{SIMPLE_KEY set_damage s_int}
|
||||
{SIMPLE_KEY set_attacks s_int}
|
||||
{SIMPLE_KEY set_parry s_int}
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
{SIMPLE_KEY icon string}
|
||||
{SIMPLE_KEY type string}
|
||||
{SIMPLE_KEY range string}
|
||||
{SIMPLE_KEY alignment alignment}
|
||||
{SIMPLE_KEY damage int}
|
||||
{SIMPLE_KEY number int}
|
||||
{SIMPLE_KEY defense_weight real}
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
#textdomain wesnoth-test
|
||||
#####
|
||||
# API(s) being tested: [attack]alignment=
|
||||
##
|
||||
# Actions:
|
||||
# Give a lawful time of day.
|
||||
# Give the leaders an alignment of lawful.
|
||||
# Have the leaders fight each other.
|
||||
##
|
||||
# Expected end state:
|
||||
# The attacker inflicted 25% more damage because the weapon alignment is lawful at a lawful time of day.
|
||||
#####
|
||||
{COMMON_KEEP_A_B_UNIT_TEST "attack_alignment_test" (
|
||||
[event]
|
||||
name=start
|
||||
[modify_unit]
|
||||
[filter]
|
||||
[/filter]
|
||||
[effect]
|
||||
apply_to=attack
|
||||
set_alignment=lawful
|
||||
[/effect]
|
||||
[/modify_unit]
|
||||
|
||||
{ATTACK_AND_VALIDATE 125}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
) TIME=MORNING}
|
||||
|
||||
#####
|
||||
# API(s) being tested: [attack]alignment=
|
||||
##
|
||||
# Actions:
|
||||
# Give an illumination ability to leaders.
|
||||
# Give the leaders an alignment of lawful.
|
||||
# Have the leaders fight each other.
|
||||
##
|
||||
# Expected end state:
|
||||
# The attacker inflicted 25% more damage because the weapon alignment is lawful and illumination provides a lawful time of day.
|
||||
#####
|
||||
{COMMON_KEEP_A_B_UNIT_TEST "attack_alignment_test_with_illuminates" (
|
||||
[event]
|
||||
name=start
|
||||
[modify_unit]
|
||||
[filter]
|
||||
[/filter]
|
||||
[effect]
|
||||
apply_to=new_ability
|
||||
[abilities]
|
||||
{ABILITY_ILLUMINATES}
|
||||
[/abilities]
|
||||
[/effect]
|
||||
[effect]
|
||||
apply_to=attack
|
||||
set_alignment=lawful
|
||||
[/effect]
|
||||
[/modify_unit]
|
||||
|
||||
{ATTACK_AND_VALIDATE 125}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
)}
|
||||
|
||||
#define FILTER_ATTACK_ALIGNMENT_TEST
|
||||
[event]
|
||||
name=start
|
||||
[modify_unit]
|
||||
[filter]
|
||||
[/filter]
|
||||
[status]
|
||||
invulnerable=yes
|
||||
[/status]
|
||||
[/modify_unit]
|
||||
[object]
|
||||
silent=yes
|
||||
[effect]
|
||||
apply_to=attack
|
||||
set_alignment=lawful
|
||||
[/effect]
|
||||
[filter]
|
||||
id=alice
|
||||
[/filter]
|
||||
[/object]
|
||||
{VARIABLE triggers_on_attack 0}
|
||||
[/event]
|
||||
[event]
|
||||
name=side 1 turn 1
|
||||
[do_command]
|
||||
[move]
|
||||
x=7,13
|
||||
y=3,4
|
||||
[/move]
|
||||
[attack]
|
||||
[source]
|
||||
x,y=13,4
|
||||
[/source]
|
||||
[destination]
|
||||
x,y=13,3
|
||||
[/destination]
|
||||
[/attack]
|
||||
[/do_command]
|
||||
[end_turn][/end_turn]
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=side 2 turn
|
||||
[do_command]
|
||||
[attack]
|
||||
[source]
|
||||
x,y=13,3
|
||||
[/source]
|
||||
[destination]
|
||||
x,y=13,4
|
||||
[/destination]
|
||||
[/attack]
|
||||
[/do_command]
|
||||
[end_turn][/end_turn]
|
||||
[/event]
|
||||
#enddef
|
||||
|
||||
# API(s) being tested: [event][filter_attack]alignment=
|
||||
##
|
||||
# Actions:
|
||||
# Give Alice alignment=lawful.
|
||||
# Define events that use filter_attack matching Alice's alignment.
|
||||
# Have Alice attack bob.
|
||||
##
|
||||
# Expected end state:
|
||||
# An event triggers when Alice attacks during side 1's turn.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST event_test_filter_attack_attack_alignment (
|
||||
{FILTER_ATTACK_ALIGNMENT_TEST}
|
||||
|
||||
# Event when Alice attacks
|
||||
[event]
|
||||
name=attack
|
||||
first_time_only=no
|
||||
[filter_attack]
|
||||
alignment=lawful
|
||||
[/filter_attack]
|
||||
{ASSERT ({VARIABLE_CONDITIONAL side_number equals 1})}
|
||||
{VARIABLE_OP triggers_on_attack add 1}
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=turn 2
|
||||
{ASSERT ({VARIABLE_CONDITIONAL triggers_on_attack equals 1})}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
)}
|
||||
|
||||
# API(s) being tested: [event][filter_attack]alignment=
|
||||
##
|
||||
# Actions:
|
||||
# Give Alice alignment=lawful.
|
||||
# Define events that use filter_attack not matching Alice's alignment.
|
||||
# Have Alice attack bob.
|
||||
##
|
||||
# Expected end state:
|
||||
# No event triggers when Alice attacks during side 1's turn.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST event_test_filter_attack_attack_alignment_no_match (
|
||||
{FILTER_ATTACK_ALIGNMENT_TEST}
|
||||
|
||||
# Event when Alice attacks
|
||||
[event]
|
||||
name=attack
|
||||
first_time_only=no
|
||||
[filter_attack]
|
||||
alignment=neutral
|
||||
[/filter_attack]
|
||||
{ASSERT ({VARIABLE_CONDITIONAL side_number equals 1})}
|
||||
{VARIABLE_OP triggers_on_attack add 1}
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=turn 2
|
||||
{ASSERT ({VARIABLE_CONDITIONAL triggers_on_attack equals 0})}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
)}
|
||||
|
||||
# API(s) being tested: [event][filter_attack]formula="alignment="
|
||||
##
|
||||
# Actions:
|
||||
# Give Alice alignment=lawful.
|
||||
# Define events that use filter_attack matching Alice's alignment.
|
||||
# Have Alice attack bob.
|
||||
##
|
||||
# Expected end state:
|
||||
# An event triggers when Alice attacks during side 1's turn.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST event_test_filter_attack_formula_attack_alignment (
|
||||
{FILTER_ATTACK_ALIGNMENT_TEST}
|
||||
|
||||
# Event when Alice attacks
|
||||
[event]
|
||||
name=attack
|
||||
first_time_only=no
|
||||
[filter_attack]
|
||||
formula="alignment='lawful'"
|
||||
[/filter_attack]
|
||||
{ASSERT ({VARIABLE_CONDITIONAL side_number equals 1})}
|
||||
{VARIABLE_OP triggers_on_attack add 1}
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=turn 2
|
||||
{ASSERT ({VARIABLE_CONDITIONAL triggers_on_attack equals 1})}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
)}
|
||||
|
||||
# API(s) being tested: [event][filter_attack]formula="alignment="
|
||||
##
|
||||
# Actions:
|
||||
# Give Alice alignment=lawful.
|
||||
# Define events that use filter_attack no matching Alice's alignment.
|
||||
# Have Alice attack bob.
|
||||
##
|
||||
# Expected end state:
|
||||
# No event triggers when Alice attacks during side 1's turn.
|
||||
#####
|
||||
{GENERIC_UNIT_TEST event_test_filter_attack_formula_attack_alignment_no_match (
|
||||
{FILTER_ATTACK_ALIGNMENT_TEST}
|
||||
|
||||
# Event when Alice attacks
|
||||
[event]
|
||||
name=attack
|
||||
first_time_only=no
|
||||
[filter_attack]
|
||||
formula="alignment='neutral'"
|
||||
[/filter_attack]
|
||||
{ASSERT ({VARIABLE_CONDITIONAL side_number equals 1})}
|
||||
{VARIABLE_OP triggers_on_attack add 1}
|
||||
[/event]
|
||||
|
||||
[event]
|
||||
name=turn 2
|
||||
{ASSERT ({VARIABLE_CONDITIONAL triggers_on_attack equals 0})}
|
||||
{SUCCEED}
|
||||
[/event]
|
||||
)}
|
||||
|
||||
#undef FILTER_ATTACK_ALIGNMENT_TEST
|
|
@ -188,7 +188,7 @@ battle_context_unit_stats::battle_context_unit_stats(nonempty_unit_const_ptr up,
|
|||
|
||||
// Time of day bonus.
|
||||
damage_multiplier += combat_modifier(
|
||||
resources::gameboard->units(), resources::gameboard->map(), u_loc, u.alignment(), u.is_fearless());
|
||||
resources::gameboard->units(), resources::gameboard->map(), u_loc, weapon->alignment(), u.is_fearless());
|
||||
|
||||
// Leadership bonus.
|
||||
int leader_bonus = under_leadership(u, u_loc, weapon, opp_weapon);
|
||||
|
@ -317,7 +317,7 @@ battle_context_unit_stats::battle_context_unit_stats(const unit_type* u_type,
|
|||
int base_damage = weapon->modified_damage();
|
||||
int damage_multiplier = 100;
|
||||
damage_multiplier
|
||||
+= generic_combat_modifier(lawful_bonus, u_type->alignment(), u_type->musthave_status("fearless"), 0);
|
||||
+= generic_combat_modifier(lawful_bonus, weapon->alignment(), u_type->musthave_status("fearless"), 0);
|
||||
damage_multiplier *= opp_type->resistance_against(weapon->type(), !attacking);
|
||||
|
||||
damage = round_damage(base_damage, damage_multiplier, 10000);
|
||||
|
|
|
@ -93,6 +93,8 @@ variant attack_type_callable::get_value(const std::string& key) const
|
|||
return variant(att_->icon());
|
||||
} else if(key == "range") {
|
||||
return variant(att_->range());
|
||||
} else if(key == "alignment") {
|
||||
return variant(att_->alignment_str());
|
||||
} else if(key == "damage") {
|
||||
return variant(att_->damage());
|
||||
} else if(key == "number_of_attacks" || key == "number" || key == "num_attacks" || key == "attacks") {
|
||||
|
@ -134,6 +136,7 @@ void attack_type_callable::get_inputs(formula_input_vector& inputs) const
|
|||
add_input(inputs, "description");
|
||||
add_input(inputs, "icon");
|
||||
add_input(inputs, "range");
|
||||
add_input(inputs, "alignment");
|
||||
add_input(inputs, "damage");
|
||||
add_input(inputs, "number");
|
||||
add_input(inputs, "accuracy");
|
||||
|
@ -174,6 +177,10 @@ int attack_type_callable::do_compare(const formula_callable* callable) const
|
|||
return att_->range().compare(att_callable->att_->range());
|
||||
}
|
||||
|
||||
if(att_->alignment_str() != att_callable->att_->alignment_str()) {
|
||||
return att_->alignment_str().compare(att_callable->att_->alignment_str());
|
||||
}
|
||||
|
||||
const auto self_specials = att_->specials().all_children_range();
|
||||
const auto other_specials = att_callable->att_->specials().all_children_range();
|
||||
if(self_specials.size() != other_specials.size()) {
|
||||
|
|
|
@ -225,7 +225,7 @@ void attack_predictions::set_data(window& window, const combatant_data& attacker
|
|||
const unit& u = *attacker.unit_;
|
||||
|
||||
const int tod_modifier = combat_modifier(resources::gameboard->units(), resources::gameboard->map(),
|
||||
u.get_location(), u.alignment(), u.is_fearless());
|
||||
u.get_location(), weapon->alignment(), u.is_fearless());
|
||||
|
||||
if(tod_modifier != 0) {
|
||||
set_label_helper("tod_modifier", utils::signed_percent(tod_modifier));
|
||||
|
|
|
@ -786,7 +786,8 @@ static int attack_info(const reports::context& rc, const attack_type &at, config
|
|||
int specials_damage = at.modified_damage();
|
||||
int damage_multiplier = 100;
|
||||
const_attack_ptr weapon = at.shared_from_this();
|
||||
int tod_bonus = combat_modifier(get_visible_time_of_day_at(rc, hex), u.alignment(), u.is_fearless());
|
||||
unit_alignments::type attack_alignment = weapon->alignment();
|
||||
int tod_bonus = combat_modifier(get_visible_time_of_day_at(rc, hex), attack_alignment, u.is_fearless());
|
||||
damage_multiplier += tod_bonus;
|
||||
int leader_bonus = under_leadership(u, hex, weapon);
|
||||
if (leader_bonus != 0)
|
||||
|
@ -958,6 +959,24 @@ static int attack_info(const reports::context& rc, const attack_type &at, config
|
|||
add_text(res, damage_and_num_attacks.str, damage_and_num_attacks.tooltip);
|
||||
add_text(res, damage_versus.str, damage_versus.tooltip); // This string is usually empty
|
||||
|
||||
if(attack_alignment != u.alignment()){
|
||||
const std::string align = unit_type::alignment_description(attack_alignment, u.gender());
|
||||
const std::string align_id = unit_alignments::get_string(attack_alignment);
|
||||
|
||||
color_t color = font::weapon_color;
|
||||
if(tod_bonus != 0) {
|
||||
color = (tod_bonus > 0) ? font::good_dmg_color : font::bad_dmg_color;
|
||||
}
|
||||
|
||||
str << " " << align << " (" << span_color(color) << utils::signed_percent(tod_bonus)
|
||||
<< naps << ")" << "\n";
|
||||
|
||||
tooltip << _("Alignment: ") << "<b>" << align << "</b>\n"
|
||||
<< string_table[align_id + "_description" ] + "\n";
|
||||
|
||||
add_text(res, flush(str), flush(tooltip));
|
||||
}
|
||||
|
||||
const std::string &accuracy_parry = at.accuracy_parry_description();
|
||||
if (!accuracy_parry.empty())
|
||||
{
|
||||
|
|
|
@ -188,6 +188,7 @@ static int impl_unit_attacks_set(lua_State* L)
|
|||
if(iter == end) {
|
||||
atk = u.add_attack(end, cfg);
|
||||
} else {
|
||||
auto ctx = atk->specials_context(u.shared_from_this(), map_location::null_location(), true);
|
||||
iter.base()->reset(new attack_type(cfg));
|
||||
atk = *iter.base();
|
||||
}
|
||||
|
@ -257,6 +258,7 @@ static int impl_unit_attack_get(lua_State *L)
|
|||
return_string_attrib("type", attack.type());
|
||||
return_string_attrib("icon", attack.icon());
|
||||
return_string_attrib("range", attack.range());
|
||||
return_string_attrib("alignment", attack.alignment_str());
|
||||
return_int_attrib("damage", attack.damage());
|
||||
return_int_attrib("number", attack.num_attacks());
|
||||
return_float_attrib("attack_weight", attack.attack_weight());
|
||||
|
@ -292,6 +294,7 @@ static int impl_unit_attack_set(lua_State *L)
|
|||
modify_string_attrib("type", attack.set_type(value));
|
||||
modify_string_attrib("icon", attack.set_icon(value));
|
||||
modify_string_attrib("range", attack.set_range(value));
|
||||
modify_string_attrib("alignment", attack.set_range(value));
|
||||
modify_int_attrib("damage", attack.set_damage(value));
|
||||
modify_int_attrib("number", attack.set_num_attacks(value));
|
||||
modify_int_attrib("attack_weight", attack.set_attack_weight(value));
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "units/attack_type.hpp"
|
||||
#include "units/unit.hpp"
|
||||
#include "formula/callable_objects.hpp"
|
||||
#include "formula/formula.hpp"
|
||||
#include "formula/string_utils.hpp"
|
||||
|
@ -79,6 +80,7 @@ attack_type::attack_type(const config& cfg) :
|
|||
range_(cfg["range"]),
|
||||
min_range_(cfg["min_range"].to_int(1)),
|
||||
max_range_(cfg["max_range"].to_int(1)),
|
||||
alignment_str_(),
|
||||
damage_(cfg["damage"]),
|
||||
num_attacks_(cfg["number"]),
|
||||
attack_weight_(cfg["attack_weight"].to_double(1.0)),
|
||||
|
@ -99,6 +101,17 @@ attack_type::attack_type(const config& cfg) :
|
|||
else
|
||||
icon_ = "attacks/blank-attack.png";
|
||||
}
|
||||
if(cfg.has_attribute("alignment") && (cfg["alignment"] == "neutral" || cfg["alignment"] == "lawful" || cfg["alignment"] == "chaotic" || cfg["alignment"] == "liminal")){
|
||||
alignment_str_ = cfg["alignment"].str();
|
||||
} else if(self_){
|
||||
alignment_str_ =unit_alignments::get_string(self_->alignment());
|
||||
}
|
||||
}
|
||||
|
||||
unit_alignments::type attack_type::alignment() const
|
||||
{
|
||||
// pick attack alignment or fall back to unit alignment
|
||||
return (unit_alignments::get_enum(alignment_str_).value_or(self_ ? self_->alignment() : unit_alignments::type::neutral));
|
||||
}
|
||||
|
||||
std::string attack_type::accuracy_parry_description() const
|
||||
|
@ -170,6 +183,7 @@ bool matches_simple_filter(const attack_type& attack, const config& filter, cons
|
|||
const std::string& filter_parry = filter["parry"];
|
||||
const std::string& filter_movement = filter["movement_used"];
|
||||
const std::string& filter_attacks_used = filter["attacks_used"];
|
||||
const std::set<std::string> filter_alignment = utils::split_set(filter["alignment"].str());
|
||||
const std::set<std::string> filter_name = utils::split_set(filter["name"].str());
|
||||
const std::set<std::string> filter_type = utils::split_set(filter["type"].str());
|
||||
const std::vector<std::string> filter_special = utils::split(filter["special"]);
|
||||
|
@ -207,6 +221,9 @@ bool matches_simple_filter(const attack_type& attack, const config& filter, cons
|
|||
if (!filter_attacks_used.empty() && !in_ranges(attack.attacks_used(), utils::parse_ranges_unsigned(filter_attacks_used)))
|
||||
return false;
|
||||
|
||||
if(!filter_alignment.empty() && filter_alignment.count(attack.alignment_str()) == 0)
|
||||
return false;
|
||||
|
||||
if ( !filter_name.empty() && filter_name.count(attack.id()) == 0)
|
||||
return false;
|
||||
|
||||
|
@ -367,6 +384,7 @@ bool attack_type::apply_modification(const config& cfg)
|
|||
const t_string& set_desc = cfg["set_description"];
|
||||
const std::string& set_type = cfg["set_type"];
|
||||
const std::string& set_range = cfg["set_range"];
|
||||
const std::string& set_attack_alignment = cfg["set_alignment"];
|
||||
const std::string& set_icon = cfg["set_icon"];
|
||||
const std::string& del_specials = cfg["remove_specials"];
|
||||
auto set_specials = cfg.optional_child("set_specials");
|
||||
|
@ -407,6 +425,10 @@ bool attack_type::apply_modification(const config& cfg)
|
|||
range_ = set_range;
|
||||
}
|
||||
|
||||
if(set_attack_alignment.empty() == false) {
|
||||
alignment_str_ = set_attack_alignment;
|
||||
}
|
||||
|
||||
if(set_icon.empty() == false) {
|
||||
icon_ = set_icon;
|
||||
}
|
||||
|
@ -748,6 +770,7 @@ void attack_type::write(config& cfg) const
|
|||
cfg["range"] = range_;
|
||||
cfg["min_range"] = min_range_;
|
||||
cfg["max_range"] = max_range_;
|
||||
cfg["alignment"] = alignment_str_;
|
||||
cfg["damage"] = damage_;
|
||||
cfg["number"] = num_attacks_;
|
||||
cfg["attack_weight"] = attack_weight_;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <boost/dynamic_bitset_fwd.hpp>
|
||||
|
||||
#include "units/ptr.hpp" // for attack_ptr
|
||||
#include "units/unit_alignments.hpp"
|
||||
|
||||
class unit_ability_list;
|
||||
class unit_type;
|
||||
|
@ -61,6 +62,7 @@ public:
|
|||
void set_range(const std::string& value) { range_ = value; set_changed(true); }
|
||||
void set_min_range(int value) { min_range_ = value; set_changed(true); }
|
||||
void set_max_range(int value) { max_range_ = value; set_changed(true); }
|
||||
void set_attack_alignment(const std::string& value) { alignment_str_ = value; set_changed(true); }
|
||||
void set_accuracy(int value) { accuracy_ = value; set_changed(true); }
|
||||
void set_parry(int value) { parry_ = value; set_changed(true); }
|
||||
void set_damage(int value) { damage_ = value; set_changed(true); }
|
||||
|
@ -85,6 +87,13 @@ public:
|
|||
std::string weapon_specials() const;
|
||||
std::string weapon_specials_value(const std::set<std::string> checking_tags) const;
|
||||
|
||||
/** Returns alignment specified by alignment_str_ variable If empty or not valid returns the unit's alignment or neutral if self_ variable empty.
|
||||
*/
|
||||
unit_alignments::type alignment() const;
|
||||
/** Returns alignment specified by alignment() for filtering.
|
||||
*/
|
||||
std::string alignment_str() const {return unit_alignments::get_string(alignment());}
|
||||
|
||||
/** Calculates the number of attacks this weapon has, considering specials. */
|
||||
void modified_attacks(unsigned & min_attacks,
|
||||
unsigned & max_attacks) const;
|
||||
|
@ -406,6 +415,7 @@ private:
|
|||
std::string icon_;
|
||||
std::string range_;
|
||||
int min_range_, max_range_;
|
||||
std::string alignment_str_;
|
||||
int damage_;
|
||||
int num_attacks_;
|
||||
double attack_weight_;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
---@field type string
|
||||
---@field icon string
|
||||
---@field range integer
|
||||
---@field alignment string
|
||||
---@field number integer
|
||||
---@field movement_used integer
|
||||
---@field attacks_used integer
|
||||
|
|
|
@ -365,6 +365,12 @@
|
|||
0 replace_special_with_filter_in_attack_event_active
|
||||
0 replace_special_with_filter_in_attack_event_inactive
|
||||
0 swarm_disables_upgrades
|
||||
0 attack_alignment_test
|
||||
0 attack_alignment_test_with_illuminates
|
||||
0 event_test_filter_attack_attack_alignment
|
||||
0 event_test_filter_attack_attack_alignment_no_match
|
||||
0 event_test_filter_attack_formula_attack_alignment
|
||||
0 event_test_filter_attack_formula_attack_alignment_no_match
|
||||
0 poison_opponent
|
||||
0 unslowable_status_test
|
||||
0 unpetrifiable_status_test
|
||||
|
|
Loading…
Add table
Reference in a new issue