Difference between revisions of "WML Abilities"

From The Battle for Wesnoth Wiki
m (Pickpocket: indent)
m (Use syntaxhighlight (works not for unbalanced WML), which changes indention in the code and smaller changes for 1.16)
Line 10: Line 10:
  
 
Use this to display the special correctly on the attacks you want:
 
Use this to display the special correctly on the attacks you want:
    #define WEAPON_SPECIAL_KNOCKBACK
+
<syntaxhighlight lang='wml'>
        [dummy]
+
#define WEAPON_SPECIAL_KNOCKBACK
            id=knockback
+
    [dummy]
            name= _ "knockback"
+
        id=knockback
            female_name= _ "female^knockback"
+
        name= _ "knockback"
            description=_ "Knockback:
+
        female_name= _ "female^knockback"
    When a unit is hit with a knockback attack, it is immediately pushed back one hex away from the attacker. Units cannot be knocked back into an occupied hex, out of villages or onto terrain they normally could not move to. Only works on offense."
+
        description=_ "When a unit is hit with a knockback attack, it is immediately pushed back one hex away from the attacker. Units cannot be knocked back into an occupied hex, out of villages or onto terrain they normally could not move to. Only works on offense."
        [/dummy]
+
    [/dummy]
    #enddef
+
#enddef
 +
</syntaxhighlight>
  
 
And insert this event to your [scenario], [multiplayer], [unit_type] or [era]:
 
And insert this event to your [scenario], [multiplayer], [unit_type] or [era]:
    [event]
+
<syntaxhighlight lang='wml'>
        name=attacker hits
+
[event]
        first_time_only=no
+
    name=attacker hits
      
+
    first_time_only=no
        [filter_attack]
+
 
            special=knockback
+
     [filter_attack]
        [/filter_attack]
+
        special_id=knockback
      
+
    [/filter_attack]
        [filter_second]
+
 
            [not]
+
     [filter_second]
                [filter_location]
+
        [not]
                    terrain=*^V*
+
            [filter_location]
                [/filter_location]
+
                terrain=*^V*
            [/not]
+
            [/filter_location]
        [/filter_second]
+
        [/not]
      
+
    [/filter_second]
         [if]
+
 
             [variable]
+
     [if]
                 name=second_unit.hitpoints
+
        [variable]
                greater_than=0
+
            name=second_unit.hitpoints
            [/variable]
+
            greater_than=0
   
+
         [/variable]
                 [store_locations]
+
 
                     [not]
+
             [store_locations]
 +
                [not]
 +
                    [filter]
 +
                    [/filter]
 +
                [/not]
 +
 
 +
                [filter_adjacent_location]
 +
                    x,y=$x2,$y2
 +
                    adjacent=-$unit.facing
 +
                [/filter_adjacent_location]
 +
 
 +
                variable=knockback_target_hex
 +
            [/store_locations]
 +
 
 +
            [if]
 +
                 [variable]
 +
                    name=knockback_target_hex.length
 +
                    greater_than=0
 +
                [/variable]
 +
 
 +
                 [then]
 +
                     [teleport]
 
                         [filter]
 
                         [filter]
 +
                            x,y=$x2,$y2
 
                         [/filter]
 
                         [/filter]
                    [/not]
+
 
   
+
                         x,y=$knockback_target_hex.x,$knockback_target_hex.y
                    [filter_adjacent_location]
+
                         ignore_passability=no
                         x,y=$x2,$y2
+
                     [/teleport]
                        adjacent=-$unit.facing
+
 
                    [/filter_adjacent_location]
+
                     [if]
   
+
                         [have_unit]
                    variable=knockback_target_hex
 
                [/store_locations]
 
   
 
                [if]
 
                    [variable]
 
                        name=knockback_target_hex.length
 
                         greater_than=0
 
                     [/variable]
 
   
 
                     [then]
 
                         [teleport]
 
                            [filter]
 
                                x,y=$x2,$y2
 
                            [/filter]
 
   
 
 
                             x,y=$knockback_target_hex.x,$knockback_target_hex.y
 
                             x,y=$knockback_target_hex.x,$knockback_target_hex.y
                            ignore_passability=no
+
                         [/have_unit]
                         [/teleport]
+
 
   
+
                         [then]
                         [if]
+
                             [sound]
                             [have_unit]
+
                                 name=fist.ogg
                                x,y=$knockback_target_hex.x,$knockback_target_hex.y
+
                            [/sound]
                            [/have_unit]
+
 
   
+
                            # the knockbacked unit doesn't seem to receive experience by default,
                            [then]
+
                            # so we need to add it manually
                                 [sound]
+
                            [store_unit]
                                    name=fist.ogg
+
                                [filter]
                                [/sound]
+
                                    x,y=$knockback_target_hex.x,$knockback_target_hex.y
   
+
                                [/filter]
                                # the knockbacked unit doesn't seem to receive experience by default,
+
 
                                # so we need to add it manually
+
                                kill=yes
                                [store_unit]
+
                                variable=knockbacked
                                    [filter]
+
                            [/store_unit]
                                        x,y=$knockback_target_hex.x,$knockback_target_hex.y
+
 
                                    [/filter]
+
                            {VARIABLE_OP knockbacked.experience add $unit.level}
   
+
 
                                    kill=yes
+
                            [unstore_unit]
                                    variable=knockbacked
+
                                variable=knockbacked
                                [/store_unit]
+
                                text= _ "knockback"
   
+
                                {COLOR_HARM}
                                {VARIABLE_OP knockbacked.experience add $unit.level}
+
                                advance=true
   
+
                            [/unstore_unit]
                                [unstore_unit]
+
 
                                    variable=knockbacked
+
                            {CLEAR_VARIABLE knockbacked}
                                    text= _ "knockback"
+
                        [/then]
                                    {COLOR_HARM}
+
                    [/if]
                                    advance=true
+
                [/then]
                                [/unstore_unit]
+
            [/if]
   
+
 
                                {CLEAR_VARIABLE knockbacked}
+
            {CLEAR_VARIABLE knockback_direction,knockback_target_hex}
                            [/then]
+
        [/then]
                        [/if]
+
    [/if]
                    [/then]
+
[/event]
                [/if]
+
</syntaxhighlight>
   
 
                {CLEAR_VARIABLE knockback_direction,knockback_target_hex}
 
            [/then]
 
        [/if]
 
    [/event]
 
  
 
=== Charm ===
 
=== Charm ===
Line 122: Line 125:
 
  {CHARM (type=Troll Whelp) fist}
 
  {CHARM (type=Troll Whelp) fist}
  
#define CHARM FILTER WEAPON
+
<syntaxhighlight lang='wml'>
    [event]
+
#define CHARM FILTER WEAPON
        name=attacker_hits
+
[event]
        first_time_only=no
+
        name=attacker_hits
+
        first_time_only=no
        [filter]
+
 
            {FILTER}
+
        [filter]
        [/filter]
+
            {FILTER}
+
        [/filter]
        [special_filter]
+
 
            weapon={WEAPON}
+
        [special_filter]
        [/special_filter]
+
            weapon={WEAPON}
+
        [/special_filter]
        {STORE_UNIT_VAR x,y=$x1,$y1 side charmer_side}
+
 
        {STORE_UNIT_VAR x,y=$x2,$y2 side charmed_side}
+
        {STORE_UNIT_VAR x,y=$x1,$y1 side charmer_side}
+
        {STORE_UNIT_VAR x,y=$x2,$y2 side charmed_side}
        {IF_VAR charmer_side not_equals $charmed_side (
+
 
            [then]
+
        {IF_VAR charmer_side not_equals $charmed_side (
                {MODIFY_UNIT x,y=$x2,$y2 variables.real_side $charmed_side}
+
            [then]
                {MODIFY_UNIT x,y=$x2,$y2 side $charmer_side}
+
                {MODIFY_UNIT x,y=$x2,$y2 variables.real_side $charmed_side}
                {MODIFY_UNIT x,y=$x2,$y2 moves 1}
+
                {MODIFY_UNIT x,y=$x2,$y2 side $charmer_side}
                {MODIFY_UNIT x,y=$x2,$y2 attacks_left 1}
+
                {MODIFY_UNIT x,y=$x2,$y2 moves 1}
+
                {MODIFY_UNIT x,y=$x2,$y2 attacks_left 1}
                {VARIABLE_OP varname format "side_$charmed_side|_units_charmed"}
+
 
                {VARIABLE $varname yes}
+
                {VARIABLE_OP varname format "side_$charmed_side|_units_charmed"}
+
                {VARIABLE $varname yes}
                {CLEAR_VARIABLE varname}
+
 
            [/then]
+
                {CLEAR_VARIABLE varname}
        )}
+
            [/then]
+
        )}
        {CLEAR_VARIABLE charmer_side}
+
 
        {CLEAR_VARIABLE charmed_side}
+
        {CLEAR_VARIABLE charmer_side,charmed_side}
    [/event]
+
    [/event]
+
 
    [event]
+
    [event]
        name=side turn
+
        name=side turn
        first_time_only=no
+
        first_time_only=no
+
 
        {VARIABLE_OP this_side_charmed to_variable "side_$side_number|_units_charmed"}
+
        {VARIABLE_OP this_side_charmed to_variable "side_$side_number|_units_charmed"}
+
 
        {IF_VAR this_side_charmed equals yes (
+
        {IF_VAR this_side_charmed equals yes (
            [then]
+
            [then]
                [store_unit]
+
                [store_unit]
                    [filter]
+
                    [filter]
                        [not]
+
                        [not]
                            side=$side_number
+
                            side=$side_number
                        [/not]
+
                        [/not]
                    [/filter]
+
                    [/filter]
+
 
                    variable=possibly_charmed
+
                    variable=possibly_charmed
                    kill=no
+
                    kill=no
                [/store_unit]
+
                [/store_unit]
+
 
                {FOREACH possibly_charmed i}
+
                {FOREACH possibly_charmed i}
                    {VARIABLE_OP real_side format "0$possibly_charmed[$i].variables.real_side"}
+
                    {VARIABLE_OP real_side format "0$possibly_charmed[$i].variables.real_side"}
+
 
                    {IF_VAR real_side not_equals "0" (
+
                    {IF_VAR real_side not_equals "0" (
                        [then]
+
                        [then]
                            {IF_VAR side_number equals $possibly_charmed[$i].variables.real_side (
+
                            {IF_VAR side_number equals $possibly_charmed[$i].variables.real_side (
                                [then]
+
                                [then]
                                    {CLEAR_VARIABLE possibly_charmed[$i].variables.real_side}
+
                                    {CLEAR_VARIABLE possibly_charmed[$i].variables.real_side}
                                    {VARIABLE possibly_charmed[$i].side $side_number}
+
                                    {VARIABLE possibly_charmed[$i].side $side_number}
+
 
                                    [unstore_unit]
+
                                    [unstore_unit]
                                        variable=possibly_charmed[$i]
+
                                        variable=possibly_charmed[$i]
                                        find_vacant=no
+
                                        find_vacant=no
                                    [/unstore_unit]
+
                                    [/unstore_unit]
                                [/then]
+
                                [/then]
                            )}
+
                            )}
                        [/then]
+
                        [/then]
                    )}
+
                    )}
                {NEXT i}
+
                {NEXT i}
+
 
                {CLEAR_VARIABLE possibly_charmed}
+
                {CLEAR_VARIABLE possibly_charmed}
            [/then]
+
            [/then]
        )}
+
        )}
    [/event]
+
    [/event]
#enddef
+
#enddef
 +
</syntaxhighlight>
  
 
=== Bloodlust ===
 
=== Bloodlust ===
Line 209: Line 213:
 
  {BLOODLUST (type=Dwarvish Ulfserker)}
 
  {BLOODLUST (type=Dwarvish Ulfserker)}
  
#define BLOODLUST FILTER
+
<syntaxhighlight lang='wml'>
    [event]
+
#define BLOODLUST FILTER
        name=die
+
    [event]
        first_time_only=no
+
        name=die
+
        first_time_only=no
        [filter_second]
+
 
            {FILTER}
+
        [filter_second]
        [/filter_second]
+
            {FILTER}
+
        [/filter_second]
        {MODIFY_UNIT x,y=$x2,$y2 moves 0}
+
 
        {MODIFY_UNIT x,y=$x2,$y2 attacks_left 1}
+
        {MODIFY_UNIT x,y=$x2,$y2 moves 0}
    [/event]
+
        {MODIFY_UNIT x,y=$x2,$y2 attacks_left 1}
#enddef
+
    [/event]
 +
#enddef
 +
</syntaxhighlight>
  
 
=== Pickpocket ===
 
=== Pickpocket ===
Line 229: Line 235:
 
To do this, use this code:
 
To do this, use this code:
  
<code>#define WEAPON_SPECIAL_PICKPOCKET<br />
+
<syntaxhighlight lang='wml'>
# Canned definition of the pickpocket ability to be included in a<br />
+
#define WEAPON_SPECIAL_PICKPOCKET
# [specials] clause.
+
    # Canned definition of the pickpocket ability to be included in a
# dummy weapon special used to describe the effect to the user
+
    # [specials] clause.
# and filter on special's id
+
    # dummy weapon special used to describe the effect to the user
[dummy]
+
    # and filter on special's id
    id=weapon_pickpocket
+
    [dummy]
    name= _ "pickpocket"
+
        id=weapon_pickpocket
    description= _ "Gain money for attacking your foe. Each strike scores you one gold."
+
        name= _ "pickpocket"
    apply_to=opponent
+
        description= _ "Gain money for attacking your foe. Each strike scores you one gold."
[/dummy]
+
        apply_to=opponent
[/specials]
+
    [/dummy]
[/attack]
+
[/specials]
# event that creates a "pickpocket has worked" variable
+
[/attack]
# and sets it to "yes" if the attacker hits at least once.
+
 
[event]
+
    # event that creates a "pickpocket has worked" variable
    name=attacker_hits
+
    # and sets it to "yes" if the attacker hits at least once.
    first_time_only=no  
+
    [event]
    [filter_attack]
+
        name=attacker_hits
        special=weapon_pickpocket
+
        first_time_only=no
    [/filter_attack]   
+
        [filter_attack]
    [store_unit]
+
            special_id=weapon_pickpocket
        [filter]
+
        [/filter_attack]   
            x,y=$x1,$y1
+
        [store_unit]
        [/filter]
+
            [filter]
        variable=unit_att_with_pickpocket
+
                x,y=$x1,$y1
        mode=append
+
            [/filter]
    [/store_unit]
+
            variable=unit_att_with_pickpocket
    [set_variable]
+
            mode=append
        name=unit_att_with_pickpocket.variables.pickpocket_has_worked
+
        [/store_unit]
        value=yes
+
        [set_variable]
    [/set_variable]
+
            name=unit_att_with_pickpocket.variables.pickpocket_has_worked
    [unstore_unit]
+
            value=yes
        variable=unit_att_with_pickpocket
+
        [/set_variable]
    [/unstore_unit]   
+
        [unstore_unit]
        {CLEAR_VARIABLE unit_att_with_pickpocket}
+
            variable=unit_att_with_pickpocket
[/event]
+
        [/unstore_unit]   
[event]
+
            {CLEAR_VARIABLE unit_att_with_pickpocket}
    name=attacker_hits
+
    [/event]
    first_time_only=no   
+
    [event]
    [filter_attack]
+
        name=attacker_hits
        special=weapon_pickpocket
+
        first_time_only=no   
    [/filter_attack]   
+
        [filter_attack]
    [store_unit]
+
            special_id=weapon_pickpocket
        [filter]
+
        [/filter_attack]   
            x,y=$x1,$y1
+
        [store_unit]
        [/filter]
+
            [filter]
        variable=pickpocketer
+
                x,y=$x1,$y1
        mode=append
+
            [/filter]
    [/store_unit]   
+
            variable=pickpocketer
    [store_unit]
+
            mode=append
        [filter]
+
        [/store_unit]   
            x,y=$x2,$y2
+
        [store_unit]
        [/filter]
+
            [filter]
        variable=pickpocketed
+
                x,y=$x2,$y2
        mode=append
+
            [/filter]
    [/store_unit]   
+
            variable=pickpocketed
    [if]
+
            mode=append
        [variable]
+
        [/store_unit]   
            name=pickpocketer.variables.pickpocket_has_worked
+
        [if]
            equals=yes
+
            [variable]
        [/variable]
+
                name=pickpocketer.variables.pickpocket_has_worked
        [then]
+
                boolean_equals=yes
            [gold]
+
            [/variable]
                side=$side_number
+
            [then]
                amount=2
+
                [gold]
            [/gold]
+
                    side=$side_number
            [unstore_unit]
+
                    amount=2
                variable=pickpocketed
+
                [/gold]
                text="!"
+
                [unstore_unit]
                {COLOR_HEAL}
+
                    variable=pickpocketed
            [/unstore_unit]
+
                    text="!"
        [/then]
+
                    {COLOR_HEAL}
    [/if]   
+
                [/unstore_unit]
    {CLEAR_VARIABLE pickpocketer}
+
            [/then]
    {CLEAR_VARIABLE pickpocketed}
+
        [/if]   
[/event]
+
        {CLEAR_VARIABLE pickpocketer,pickpocketed}
[+attack]
+
    [/event]
[+specials]
+
    [+attack]
#enddef</code>
+
    [+specials]
 +
#enddef
 +
</syntaxhighlight>
  
 
It can be placed after the [unit_type] tag, or in its own .cfg file.
 
It can be placed after the [unit_type] tag, or in its own .cfg file.
 
 
  
  
 
To change the amount of gold given per hit, change
 
To change the amount of gold given per hit, change
    <code>[gold]
+
[gold]
    side=$side_number
+
    side=$side_number
    amount='''X'''
+
    amount='''X'''
    [/gold]</code>
+
[/gold]
 
Where '''X''' is the amount of gold you want.
 
Where '''X''' is the amount of gold you want.
 
 
  
  
 
If you want the gold to be constant, given at the end of the turn if at least one of the attack hits, instead of '''X''' amount of gold per hit, change
 
If you want the gold to be constant, given at the end of the turn if at least one of the attack hits, instead of '''X''' amount of gold per hit, change
  <code>[event]
+
  [event]
  '''name=attacker_hits'''
+
    '''name=attacker_hits'''
  first_time_only=no</code>
+
    first_time_only=no</code>
  
 
to
 
to
  
  <code>[event]
+
  [event]
  '''name=attack_end'''
+
    '''name=attack_end'''
  first_time_only=no</code>
+
    first_time_only=no
  
 
===Soultaker===
 
===Soultaker===
  
Any unit with this ability will gain an additional point of damage per strike every time it kills an enemy. Coder(s) unknown, made for Melon's Youkai faction (http://www.wesnoth.org/forum/viewtopic.php?f=19&t=20100).
+
Any unit with this ability will gain an additional point of damage per strike every time it kills an enemy. Coder(s) unknown, made for Melon's Youkai faction (https://r.wesnoth.org/t20100).
  
 
To give a unit the ability, place the following in any .cfg file loaded by the campaign or era:
 
To give a unit the ability, place the following in any .cfg file loaded by the campaign or era:
  
#define ABILITY_SOULTAKER
+
<syntaxhighlight lang='wml'>
[dummy]
+
#define ABILITY_SOULTAKER
id=soultaker
+
  [dummy]
name= _ "soultaker"
+
      id=soultaker
description=_ "Soultaker:
+
      name= _ "soultaker"
This unit gains an additional point added to its maximum damage whenever it kills a living unit."
+
      description=_ "This unit gains an additional point added to its melee damage whenever it kills a living unit."
[/dummy]
+
  [/dummy]
+
[/abilities]
[/abilities]
+
 
[event]
+
[event]
name=die
+
    name=die
first_time_only=no
+
    first_time_only=no
[filter]
+
    [filter]
[not]
+
        [not]
[wml_filter]
+
            status=not_living
[status]
+
        [/not]
not_living="yes"
+
    [/filter]
[/status]
+
 
[/wml_filter]
+
    [filter_second]
[/not]
+
        ability=soultaker
[/filter]
+
    [/filter_second]
+
 
[filter_second]
+
    [unstore_unit]
ability=soultaker
+
        variable=second_unit
[/filter_second]
+
        {COLOR_HEAL}
+
        text= _ "+1 damage"
[unstore_unit]
+
    [/unstore_unit]
variable=second_unit
+
 
{COLOR_HEAL}
+
    [object]
text= _ "+1 damage"
+
        silent=yes
find_vacant=no
+
        duration=forever
[/unstore_unit]
+
        [filter]
+
            x,y=$x2,$y2
[object]
+
        [/filter]
silent=yes
+
 
duration=forever
+
        [effect]
[filter]
+
            apply_to=attack
x,y=$x2,$y2
+
            range=melee
[/filter]
+
            increase_damage=1
+
        [/effect]
[effect]
+
    [/object]
apply_to=attack
+
[/event]
range=melee
+
 
increase_damage=1
+
[+abilities]
increase=1
+
#enddef
[/effect]
+
</syntaxhighlight>
[/object]
 
[/event]
 
 
[+abilities]
 
#enddef
 
  
 
And the following in the unit's [abilities] tag:
 
And the following in the unit's [abilities] tag:
  
{ABILITY_SOULTAKER}
+
{ABILITY_SOULTAKER}
  
 
===Soultaker (weapon special)===
 
===Soultaker (weapon special)===
  
Unit with this weapon special will gain an additional point of damage per strike for that weapon every time it kills an enemy with this attack. Coder Ravana, made for ageless era (http://forums.wesnoth.org/viewtopic.php?f=19&t=25274) based on previous ability.
+
Unit with this weapon special will gain an additional point of damage per strike for that weapon every time it kills an enemy with this attack. Coder Ravana, made for ageless era (https://r.wesnoth.org/t25274) based on previous ability.
  
 
To give a unit the weapon special, load the following code:
 
To give a unit the weapon special, load the following code:
  
#define WEAPON_SPECIAL_SOULTAKER
+
<syntaxhighlight lang='wml'>
  [dummy]
+
#define WEAPON_SPECIAL_SOULTAKER
  id=soultaker
+
    [dummy]
  name= _ "soultaker"
+
        id=soultaker
  description=_"Soultaker:
+
        name= _ "soultaker"
This unit gains an additional point added to its maximum damage whenever it kills a living unit."
+
        description=_"This unit gains an additional point added to its damage whenever it kills a living unit."
  [/dummy]
+
    [/dummy]
[/specials]
+
[/specials]
[/attack]
+
[/attack]
[event]
+
 
  name=die
+
[event]
  first_time_only=no
+
    name=die
  id=soultaker_event
+
    first_time_only=no
  [filter]
+
    id=soultaker_event
  [not]
+
    [filter]
    [filter_wml]
+
        [not]
    [status]
+
            status=not_living
      not_living="yes"
+
        [/not]
    [/status]
+
     [/filter]
     [/filter_wml]
+
    [filter_second_attack]
  [/not]
+
        special_id=soultaker
  [/filter]
+
    [/filter_second_attack]
  [filter_second_attack]
+
    [unstore_unit]
  special=soultaker
+
        variable=second_unit
  [/filter_second_attack]
+
        {COLOR_HEAL}
  [unstore_unit]
+
        text= _ "+1 damage"
  variable=second_unit
+
    [/unstore_unit]
  {COLOR_HEAL}
+
    [object]
  text= _ "+1 damage"
+
        silent=yes
  find_vacant=no
+
        duration=forever
  [/unstore_unit]
+
        [filter]
  [object]
+
            x,y=$x2,$y2
  silent=yes
+
        [/filter]
  duration=forever
+
        [effect]
  [filter]
+
            apply_to=attack
    x,y=$x2,$y2
+
            name=$second_weapon.name
  [/filter]
+
            increase_damage=1
  [effect]
+
        [/effect]
    apply_to=attack
+
    [/object]
    name=$second_weapon.name
+
[/event]
    increase_damage=1
+
[+attack]
  [/effect]
+
    [+specials]
  [/object]
+
#enddef
[/event]
+
</syntaxhighlight>
[+attack]
+
 
  [+specials]
 
#enddef
 
  
 
And the following in the attack's [specials] tag:
 
And the following in the attack's [specials] tag:
  
  {WEAPON_SPECIAL_SOULTAKER}
+
{WEAPON_SPECIAL_SOULTAKER}
  
 
===Charm (Type 2)===
 
===Charm (Type 2)===
  
An attack special. If the attack hits, and the target is level 0 or 1, the target is converted to the attacker's side. However, if it misses, the attacker is converted to the defender's side. Maintainer is krotop, using 1.6.x syntax (and compatible with 1.7.x], made for Melon's Youkai faction (http://www.wesnoth.org/forum/viewtopic.php?f=21&t=22539)
+
An attack special. If the attack hits, and the target is level 0 or 1, the target is converted to the attacker's side. However, if it misses, the attacker is converted to the defender's side. Maintainer is krotop, using 1.6.x syntax (and compatible with 1.7.x], made for Melon's Youkai faction (https://r.wesnoth.org/t22539)
 +
 
 +
 
 +
<syntaxhighlight lang='wml'>
 +
    #define WEAPON_SPECIAL_CHARM
 +
    # Canned definition of the Charm ability to be included in a
 +
    # [specials] clause.
 +
 
 +
    # dummy weapon special used to describe the effect to the user
 +
    # and filter on special's id
 +
    [dummy]
 +
        id=weapon_charm
 +
        name= _ "charm"
 +
        description= _ "Turns a living level 1 or level 0 unit to your side. Beware  if all of your attacks miss, the charm user turns to the defender side, even if it is your leader. You can not charm an ennemy leader or a non-living creature."
 +
        apply_to=opponent
 +
    [/dummy]
  
 +
    [/specials]
 +
    [/attack]
  
#define WEAPON_SPECIAL_CHARM
+
    # event that creates a variable at the beginning of the fight to check if the attacker hit at least once by the end.
# Canned definition of the Charm ability to be included in a
+
    [event]
# [specials] clause.
+
        name=attack
+
        first_time_only=no
+
       
# dummy weapon special used to describe the effect to the user
+
        [filter_attack]
# and filter on special's id
+
            special_id=weapon_charm
[dummy]
+
        [/filter_attack]
id=weapon_charm
+
       
name= _ "charm"
+
        [store_unit]
name_inactive= _ "charm"
+
            [filter]
description= _ "Charm :
+
                x,y=$x1,$y1
Turns a living level 1 or level 0 unit to your side. Beware  if all of your attacks miss, the charm user turns to the defender side, even if it is your leader. You can not charm an ennemy leader or a non-living creature."
+
            [/filter]
description_inactive= _ "Charm :
+
            variable=unit_att_with_charm
Turns a living level 1 or level 0 unit to your side. Beware  if all of your attacks miss, the charm user turns to the defender side, even if it is your leader. You can not charm an ennemy leader or a non-living creature."
+
            mode=append
apply_to=opponent
+
        [/store_unit]  
[/dummy]
+
        [set_variable]
+
            name=unit_att_with_charm.variables.charm_has_worked
[/specials]
+
            value=no
[/attack]
+
        [/set_variable]  
+
        [unstore_unit]
# event that creates a variable at the beginning of the fight to check if the attacker hit at least once by the end.
+
            variable=unit_att_with_charm
[event]
+
        [/unstore_unit]
name=attack
+
       
first_time_only=no
+
        {CLEAR_VARIABLE unit_att_with_charm}
+
    [/event]
[filter_attack]
+
 
special=weapon_charm
+
    # event that creates a "charm has worked" variable
[/filter_attack]
+
    # and sets it to "yes" if the attacker hits at least once.
+
    [event]
[store_unit]
+
        name=attacker_hits
[filter]
+
        first_time_only=no
x,y=$x1,$y1
+
       
[/filter]
+
        [filter_attack]
variable=unit_att_with_charm
+
            special_id=weapon_charm
mode=append
+
        [/filter_attack]
[/store_unit]
+
       
[set_variable]
+
        [store_unit]
name=unit_att_with_charm.variables.charm_has_worked
+
            [filter]
value=no
+
                x,y=$x1,$y1
[/set_variable]
+
            [/filter]
[unstore_unit]
+
            variable=unit_att_with_charm
variable=unit_att_with_charm
+
            mode=append
[/unstore_unit]
+
        [/store_unit]
+
        [set_variable]
{CLEAR_VARIABLE unit_att_with_charm}
+
            name=unit_att_with_charm.variables.charm_has_worked
[/event]
+
            value=yes
+
        [/set_variable]
+
        [unstore_unit]
# event that creates a "charm has worked" variable
+
            variable=unit_att_with_charm
# and sets it to "yes" if the attacker hits at least once.
+
        [/unstore_unit]
[event]
+
       
name=attacker_hits
+
        {CLEAR_VARIABLE unit_att_with_charm}
first_time_only=no
+
    [/event]
+
 
[filter_attack]
+
    # event that shifts a unit to the other side
special=weapon_charm
+
    # if the defending unit
[/filter_attack]
+
    #      - was not lvl1 or lvl0  
+
    #      - and was not a recruiting unit  
[store_unit]
+
    #      - and was a not a "non-living" creature
[filter]
+
    # then :
x,y=$x1,$y1
+
    # -> if the attacker missed all attacks, it goes to the defender side.
[/filter]
+
    # -> if the attacker hit once at least, the defender goes to the attacker side.
variable=unit_att_with_charm
+
    [event]
mode=append
+
        name=attack_end
[/store_unit]
+
        first_time_only=no
[set_variable]
+
       
name=unit_att_with_charm.variables.charm_has_worked
+
        [filter_attack]
value=yes
+
            special_id=weapon_charm
[/set_variable]
+
        [/filter_attack]
[unstore_unit]
+
        [filter_second]
variable=unit_att_with_charm
+
            canrecruit=no
[/unstore_unit]
+
            [and]
+
                level=0
{CLEAR_VARIABLE unit_att_with_charm}
+
                [or]
[/event]
+
                    level=1
+
                [/or]
+
            [/and]
# event that shifts a unit to the other side
+
            [and]
# if the defending unit
+
                [not]
#      - was not lvl1 or lvl0  
+
                    status=not_living
#      - and was not a recruiting unit  
+
                [/not]
#      - and was a not a "non-living" creature
+
            [/and]
# then :
+
        [/filter_second]
# -> if the attacker missed all attacks, it goes to the defender side.
+
       
# -> if the attacker hit once at least, the defender goes to the attacker side.
+
        [store_unit]
[event]
+
            [filter]
name=attack_end
+
                x,y=$x1,$y1
first_time_only=no
+
            [/filter]
+
            variable=charmer
[filter_attack]
+
            mode=append
special=weapon_charm
+
        [/store_unit]
[/filter_attack]
+
       
[filter_second]
+
        [store_unit]
canrecruit=no
+
            [filter]
[and]
+
                x,y=$x2,$y2
level=0
+
            [/filter]
[or]
+
            variable=charmed
level=1
+
            mode=append
[/or]
+
        [/store_unit]
[/and]
+
       
[and]
+
        [if]
[not]
+
            [variable]
[filter_wml]
+
                name=charmer.variables.charm_has_worked
[status]
+
                boolean_equals=no
not_living=yes
+
            [/variable]
[/status]
+
            [then]
[/filter_wml]
+
                [set_variable]
[/not]
+
                    name=charmer.side
[/and]
+
                    value=$charmed.side
[/filter_second]
+
                [/set_variable]
+
                [unstore_unit]
[store_unit]
+
                    variable=charmer
[filter]
+
                    text="Charm failed!"
x,y=$x1,$y1
+
                    {COLOR_HARM}
[/filter]
+
                [/unstore_unit]
variable=charmer
+
            [/then]
mode=append
+
            [else]
[/store_unit]
+
                [set_variable]
+
                    name=charmed.side
[store_unit]
+
                    value=$charmer.side
[filter]
+
                [/set_variable]
x,y=$x2,$y2
+
                [unstore_unit]
[/filter]
+
                    variable=charmed
variable=charmed
+
                    text="Charmed!"
mode=append
+
                    {COLOR_HEAL}
[/store_unit]
+
                [/unstore_unit]
+
            [/else]
[if]
+
        [/if]
[variable]
+
 
name=charmer.variables.charm_has_worked
+
        {CLEAR_VARIABLE charmer,charmed}
equals=no
+
    [/event]
[/variable]
+
 
[then]
+
    [+attack]
[set_variable]
+
    [+specials]
name=charmer.side
+
#enddef
value=$charmed.side
+
</syntaxhighlight>
[/set_variable]
 
[unstore_unit]
 
variable=charmer
 
text="Charm failed!"
 
{COLOR_HARM}
 
[/unstore_unit]
 
[/then]
 
[else]
 
[set_variable]
 
name=charmed.side
 
value=$charmer.side
 
[/set_variable]
 
[unstore_unit]
 
variable=charmed
 
text="Charmed!"
 
  {COLOR_HEAL}
 
[/unstore_unit]
 
[/else]
 
[/if]
 
 
{CLEAR_VARIABLE charmer}
 
{CLEAR_VARIABLE charmed}
 
[/event]
 
 
[+attack]
 
[+specials]
 
 
#enddef
 
  
 
== Works ==
 
== Works ==
Line 632: Line 618:
  
 
Put this macro into you code before the last piece of code.
 
Put this macro into you code before the last piece of code.
<pre>
+
<syntaxhighlight lang='wml'>
 
#define ABILITY_WORKS
 
#define ABILITY_WORKS
    [leadership]
+
    [leadership]
          value=0
+
        value=0
          id=peasant_works
+
        id=peasant_works
          cumulative=no
+
        cumulative=no
          name="works"
+
        name="works"
          description= _ "Works:
+
        description= _ "This unit produces 1 gold per turn."
This unit produces 1 gold per turn."
 
 
     [/leadership]
 
     [/leadership]
#enddef
+
#enddef
</pre>
+
</syntaxhighlight>
  
 
Put this event into your code.
 
Put this event into your code.
<pre>
+
<syntaxhighlight lang='wml'>
 
[event]
 
[event]
name=side turn
+
    name=side turn
first_time_only=no
+
    first_time_only=no
[store_unit]
+
    [store_unit]
[filter]
+
        [filter]
            #your filter here... for example type=Peasant
+
            # your filter here... for example type=Peasant
[/filter]
+
        [/filter]
variable=worker
+
        variable=worker
kill=no
+
    [/store_unit]
[/store_unit]
 
  
{FOREACH worker i}
+
        {FOREACH worker i}
+
   
[gold]
+
            [gold]
                            side=$side_number  
+
                side=$side_number  
                            amount=1
+
                amount=1
                        [/gold]  
+
            [/gold]  
[unstore_unit]
+
            [unstore_unit]
variable=worker[$i]
+
                variable=worker[$i]
text="1"
+
                text="1"
        red,green,blue=255,255,0  
+
                red,green,blue=255,255,0  
[/unstore_unit]
+
            [/unstore_unit]
+
               
{NEXT i}
+
        {NEXT i}
+
   
{CLEAR_VARIABLE worker}
+
    {CLEAR_VARIABLE worker}
[/event]
+
[/event]
</pre>
+
</syntaxhighlight>
  
 
And give the unit the ability like this
 
And give the unit the ability like this
<pre>
+
 
[object]
+
<syntaxhighlight lang='wml'>
    silent=yes
+
[object]
    [effect]
+
    silent=yes
apply_to=new_ability
+
    [effect]
          [abilities]
+
        apply_to=new_ability
            {ABILITY_WORKS}
+
        [abilities]
          [/abilities]
+
            {ABILITY_WORKS}
 +
        [/abilities]
 
     [/effect]
 
     [/effect]
 
  [/object]
 
  [/object]
</pre>
+
</syntaxhighlight>
 
 
  
 
== Mind Flay  ==
 
== Mind Flay  ==
Line 695: Line 679:
  
 
Give this special to the attack(s) you want it to have.  
 
Give this special to the attack(s) you want it to have.  
#define WEAPON_SPECIAL_MIND_FLAY
+
<syntaxhighlight lang='wml'>
 +
#define WEAPON_SPECIAL_MIND_FLAY
 
     [mindflay]
 
     [mindflay]
 
         id=mind_flay
 
         id=mind_flay
Line 701: Line 686:
 
         description="When used offensively, each hit of the mind flay attack takes 1 point of experience from the defender and gives it to the attacker."
 
         description="When used offensively, each hit of the mind flay attack takes 1 point of experience from the defender and gives it to the attacker."
 
     [/mindflay]
 
     [/mindflay]
#enddef
+
#enddef
 +
</syntaxhighlight>
 +
 
  
 
Include these events into your scenario.
 
Include these events into your scenario.
[event]
+
<syntaxhighlight lang='wml'>
name=attack
+
[event]
first_time_only=no
+
    name=attack
[special_filter]
+
    first_time_only=no
weapon=mind flay
+
    [special_filter]
[/special_filter]
+
        weapon=mind flay
{VARIABLE hit_number 0}
+
    [/special_filter]
[/event]
+
    {VARIABLE hit_number 0}
[event]
+
[/event]
name=attacker_hits
+
[event]
first_time_only=no
+
    name=attacker_hits
[special_filter]
+
    first_time_only=no
weapon=mind flay
+
    [special_filter]
[/special_filter]
+
        weapon=mind flay
{VARIABLE_OP hit_number add 1}
+
    [/special_filter]
[/event]
+
    {VARIABLE_OP hit_number add 1}
[event]
+
[/event]
name=attack_end
+
[event]
first_time_only=no
+
    name=attack_end
[special_filter]
+
    first_time_only=no
weapon=mind flay
+
    [special_filter]
[/special_filter]
+
        weapon=mind flay
{VARIABLE_OP second_unit.experience add -$hit_number}
+
    [/special_filter]
{VARIABLE_OP unit.experience add $hit_number}
+
    {VARIABLE_OP second_unit.experience add -$hit_number}
[unstore_unit]
+
    {VARIABLE_OP unit.experience add $hit_number}
variable=unit
+
    [unstore_unit]
find_vacant=no
+
        variable=unit
text=$hit_number
+
        find_vacant=no
blue=255
+
        text=$hit_number
[/unstore_unit]
+
        blue=255
[unstore_unit]
+
    [/unstore_unit]
variable=second_unit
+
    [unstore_unit]
find_vacant=no
+
        variable=second_unit
[/unstore_unit]
+
        find_vacant=no
{CLEAR_VARIABLE hit_number}
+
    [/unstore_unit]
[/event]
+
    {CLEAR_VARIABLE hit_number}
 +
[/event]
 +
</syntaxhighlight>
  
 
Note: In dev version substitute "name=" instead of "weapon=".
 
Note: In dev version substitute "name=" instead of "weapon=".
Line 747: Line 736:
 
Initiative is an aura ability. Much like Leadership, it affects adjacent allies but not the unit itself.
 
Initiative is an aura ability. Much like Leadership, it affects adjacent allies but not the unit itself.
  
#define AURA_INITIATIVE TYPE
+
<syntaxhighlight lang='wml'>
[dummy]
+
#define AURA_INITIATIVE TYPE
id=initiative
+
    [dummy]
name= _ "initiative"
+
        id=initiative
description= _ "Initiative:
+
        name= _ "initiative"
Adjacent allies are granted Firststrike with all weapons."
+
        description= _ "Adjacent allies are granted Firststrike with all weapons."
[/dummy]
+
    [/dummy]
[/abilities]
+
[/abilities]
[event]
+
 
name=attack
+
    [event]
first_time_only=no
+
        name=attack
 +
        first_time_only=no
 
   
 
   
[filter]
+
        [filter]
[filter_adjacent]
+
            [filter_adjacent]
type={TYPE}
+
                type={TYPE}
is_enemy=no
+
                is_enemy=no
[/filter_adjacent]
+
            [/filter_adjacent]
[/filter]
+
        [/filter]
+
       
{FOREACH unit.attack i}
+
        {FOREACH unit.attack i}
{VARIABLE unit.attack[$i].specials.firststrike.id "firststrike"}
+
            {VARIABLE unit.attack[$i].specials.firststrike.id "firststrike"}
{NEXT i}
+
        {NEXT i}
+
       
[unstore_unit]
+
        [unstore_unit]
variable=unit
+
            variable=unit
[/unstore_unit]
+
        [/unstore_unit]
[/event]
+
    [/event]
[event]
+
    [event]
name=attack
+
        name=attack
first_time_only=no
+
        first_time_only=no
 
   
 
   
[filter_second]
+
        [filter_second]
[filter_adjacent]
+
            [filter_adjacent]
type={TYPE}
+
                type={TYPE}
is_enemy=no
+
                is_enemy=no
[/filter_adjacent]
+
            [/filter_adjacent]
[/filter_second]
+
        [/filter_second]
+
       
{FOREACH second_unit.attack i}
+
        {FOREACH second_unit.attack i}
{VARIABLE second_unit.attack[$i].specials.firststrike.id "firststrike"}
+
            {VARIABLE second_unit.attack[$i].specials.firststrike.id "firststrike"}
{NEXT i}
+
        {NEXT i}
+
       
[unstore_unit]
+
        [unstore_unit]
variable=second_unit
+
            variable=second_unit
[/unstore_unit]
+
        [/unstore_unit]
[/event]
+
    [/event]
[event]
+
    [event]
name=attack_end
+
        name=attack_end
first_time_only=no
+
        first_time_only=no
 
   
 
   
[filter]
+
        [filter]
[wml_filter]
+
            [wml_filter]
[attack]
+
                [attack]
[specials]
+
                    [specials]
[firststrike]
+
                        [firststrike]
id=firststrike
+
                            id=firststrike
[/firststrike]
+
                        [/firststrike]
[/specials]
+
                    [/specials]
[/attack]
+
                [/attack]
[/wml_filter]
+
            [/wml_filter]
[/filter]
+
        [/filter]
+
       
{FOREACH unit.attack i}
+
        {FOREACH unit.attack i}
{CLEAR_VARIABLE unit.attack[$i].specials.firststrike}
+
            {CLEAR_VARIABLE unit.attack[$i].specials.firststrike}
{NEXT i}
+
        {NEXT i}
+
       
[unstore_unit]
+
        [unstore_unit]
variable=unit
+
            variable=unit
[/unstore_unit]
+
        [/unstore_unit]
[/event]
+
    [/event]
[event]
+
    [event]
name=attack_end
+
        name=attack_end
first_time_only=no
+
        first_time_only=no
 
   
 
   
[filter_second]
+
        [filter_second]
[wml_filter]
+
            [wml_filter]
[attack]
+
                [attack]
[specials]
+
                    [specials]
[firststrike]
+
                        [firststrike]
id=firststrike
+
                            id=firststrike
[/firststrike]
+
                        [/firststrike]
[/specials]
+
                    [/specials]
[/attack]
+
                [/attack]
[/wml_filter]
+
            [/wml_filter]
[/filter_second]
+
        [/filter_second]
+
       
{FOREACH second_unit.attack i}
+
        {FOREACH second_unit.attack i}
{CLEAR_VARIABLE second_unit.attack[$i].specials.firststrike}
+
            {CLEAR_VARIABLE second_unit.attack[$i].specials.firststrike}
{NEXT i}
+
        {NEXT i}
+
       
[unstore_unit]
+
        [unstore_unit]
variable=second_unit
+
            variable=second_unit
[/unstore_unit]
+
        [/unstore_unit]
[/event]
+
    [/event]
[+abilities]
+
[+abilities]
#enddef
+
#enddef
 +
</syntaxhighlight>
  
 
A WML filter may be added instead of the type if you want some units of that type to not have the ability.
 
A WML filter may be added instead of the type if you want some units of that type to not have the ability.
Line 850: Line 841:
 
Blitz is an aura ability. Much like Leadership, it affects adjacent allies but not the unit itself.
 
Blitz is an aura ability. Much like Leadership, it affects adjacent allies but not the unit itself.
  
#define AURA_BLITZ TYPE
+
<syntaxhighlight lang='wml'>
[dummy]
+
#define AURA_BLITZ TYPE
id=blitz
+
    [dummy]
name= _ "blitz"
+
        id=blitz  
description= _ "Blitz:
+
        name= _ "blitz"
Allies that start their turn adjacent to this unit are granted Skirmisher for that turn."
+
        description= _ "Allies that start their turn adjacent to this unit are granted Skirmisher for that turn."
[/dummy]
+
    [/dummy]
[/abilities]
+
[/abilities]
[event]
+
 
name=side turn
+
    [event]
first_time_only=no
+
        name=side turn
+
        first_time_only=no
[store_unit]
+
       
[filter]
+
        [store_unit]
+
            [filter]
[wml_filter]
+
                [wml_filter]
blitzed=1
+
                    blitzed=1
[/wml_filter]
+
                [/wml_filter]
[/filter]
+
            [/filter]
variable=blitz_refresh
+
            variable=blitz_refresh
[/store_unit]
+
        [/store_unit]
+
       
{FOREACH blitz_refresh i}
+
        {FOREACH blitz_refresh i}
{CLEAR_VARIABLE blitz_refresh[$i].abilities.skirmisher}
+
            {CLEAR_VARIABLE blitz_refresh[$i].abilities.skirmisher}
{VARIABLE blitz_refresh[$i].blitzed 0}
+
            {VARIABLE blitz_refresh[$i].blitzed 0}
[unstore_unit]
+
            [unstore_unit]
variable=blitz_refresh[$i]
+
                variable=blitz_refresh[$i]
[/unstore_unit]
+
            [/unstore_unit]
{NEXT i}
+
        {NEXT i}
 
   
 
   
[store_unit]
+
        [store_unit]
[filter]
+
            [filter]
side=$side_number
+
                side=$side_number
[filter_adjacent]
+
                [filter_adjacent]
type={TYPE}
+
                    type={TYPE}
is_enemy=no
+
                    is_enemy=no
[/filter_adjacent]
+
                [/filter_adjacent]
[/filter]
+
            [/filter]
variable=blitzed
+
            variable=blitzed
[/store_unit]
+
        [/store_unit]
+
       
{FOREACH blitzed i}
+
        {FOREACH blitzed i}
[if]
+
            [if]
[variable]
+
                [variable]
name=blitzed[$i].abilities.skirmisher.id
+
                    name=blitzed[$i].abilities.skirmisher.id
not_equals="skirmisher"
+
                    not_equals="skirmisher"
[/variable]
+
                [/variable]
[then]
+
                [then]
{VARIABLE blitzed[$i].blitzed 1}
+
                    {VARIABLE blitzed[$i].blitzed 1}
{VARIABLE blitzed[$i].abilities.skirmisher.id skirmisher}
+
                    {VARIABLE blitzed[$i].abilities.skirmisher.id skirmisher}
{VARIABLE blitzed[$i].abilities.skirmisher.name "skirmisher"}
+
                    {VARIABLE blitzed[$i].abilities.skirmisher.name "skirmisher"}
{VARIABLE blitzed[$i].abilities.skirmisher.description  "Skirmisher:
+
                    {VARIABLE blitzed[$i].abilities.skirmisher.description  "This unit is skilled in moving past enemies quickly, and ignores all enemy Zones of Control."}
This unit is skilled in moving past enemies quickly, and ignores all enemy Zones of Control."}
+
                    [unstore_unit]
[unstore_unit]
+
                        variable=blitzed[$i]
variable=blitzed[$i]
+
                    [/unstore_unit]
[/unstore_unit]
+
                [/then]
[/then]
+
            [/if]
[/if]
+
        {NEXT i}
{NEXT i}
+
    [/event]
[/event]
+
[+abilities]
[+abilities]
+
#enddef
#enddef
+
</syntaxhighlight>
  
 
== Immune to drain or plague or poison ==
 
== Immune to drain or plague or poison ==
Line 1,015: Line 1,006:
  
 
This is the part that is the weapon special that marks it.
 
This is the part that is the weapon special that marks it.
[attacks]      #This can be changed to a dummy tag if you don't want it to do anything.
+
<syntaxhighlight lang='wml'>
        id=whirlwind
+
[attacks]      #This can be changed to a dummy tag if you don't want it to do anything.
        name= _ "whirlwind"
+
    id=whirlwind
        name_inactive= _ "whirlwind"
+
    name= _ "whirlwind"
        description= _ "Whirlwind: When this attack is used, all units adjacent the attacker take the damage, and cannot be countered."
+
    description= _ "When this attack is used, all units adjacent the attacker take the damage, and cannot be countered."
        description_inactive= _ "Whirlwind: When this attack is used, all units adjacent the attacker take the damage, and cannot be countered."
+
    value=0
        value=0
+
    apply_to=opponent
        apply_to=opponent
+
[/attacks]
[/attacks]
+
</syntaxhighlight>
 
 
  
  
 
This is the event.
 
This is the event.
 
  [event]
 
  [event]
name=attacker_hits
+
    name=attacker_hits
first_time_only=no
+
    first_time_only=no
[filter_attack]
+
    [filter_attack]
        special=whirlwind
+
        special_id=whirlwind
[/filter_attack]
+
    [/filter_attack]
{VARIABLE has_drain 0} # Notifies the weapon specials
+
    {VARIABLE has_drain 0}     # Notifies the weapon specials
{VARIABLE has_slow no}
+
    {VARIABLE has_slow no}
{VARIABLE has_poison no}
+
    {VARIABLE has_poison no}
{FOREACH weapon.specials.damage i}
+
    {FOREACH weapon.specials.damage i}
[if]
+
    [if]
[variable]
+
        [variable]
name=weapon.specials.drains.id
+
            name=weapon.specials.drains.id
equals=drains
+
            equals=drains
[/variable]
+
        [/variable]
[then]
+
        [then]
{VARIABLE has_drain 1}
+
            {VARIABLE has_drain 1}
 
   
 
   
[/then]
+
        [/then]
[/if]
+
    [/if]
{NEXT i}
+
    {NEXT i}
[if]
+
    [if]
[variable]
+
        [variable]
name=weapon.specials.poison.id
+
            name=weapon.specials.poison.id
equals=poison
+
            equals=poison
[/variable]
+
        [/variable]
[then]
+
        [then]
{VARIABLE has_poison yes}
+
            {VARIABLE has_poison yes}
 
   
 
   
[/then]
+
        [/then]
[/if]
+
    [/if]
[if]
+
    [if]
[variable]
+
        [variable]
name=weapon.specials.slow.id
+
            name=weapon.specials.slow.id
equals=slow
+
            equals=slow
[/variable]
+
        [/variable]
[then]
+
        [then]
{VARIABLE has_slow yes}
+
            {VARIABLE has_slow yes}
 
   
 
   
  [/then]
+
        [/then]
[/if]
+
    [/if]
[if]
+
    [if]
[variable]
+
        [variable]
name=has_drain
+
            name=has_drain
equals=0
+
            equals=0
[/variable]
+
        [/variable]
[else]
+
        [else]
[store_unit] #We need to know how many units were drained, and what were their resistances
+
            [store_unit]       #We need to know how many units were drained, and what were their resistances
  [filter]
+
                [filter]
[filter_adjacent]
+
                    [filter_adjacent]
x,y=$x1,$y1
+
                        x,y=$x1,$y1
[/filter_adjacent]
+
                    [/filter_adjacent]
[not]
+
                    [not]
side=1             #If you want to use it in an era, use side=$unit.side instead
+
                        side=1             #If you want to use it in an era, use side=$unit.side instead
[/not]
+
                    [/not]
[not]        #The target unit is already hit by the attack
+
                    [not]        #The target unit is already hit by the attack
x,y=$x2,$y2
+
                        x,y=$x2,$y2
[/not]
+
                    [/not]
[not]          #Undead are undrainable
+
                    [not]          #Undead are undrainable
race=undead
+
                        race=undead
[/not]
+
                    [/not]
[/filter]
+
                [/filter]
variable=units
+
                variable=units
[/store_unit]   
+
            [/store_unit]   
{VARIABLE healed_amount 0}
+
            {VARIABLE healed_amount 0}
  {FOREACH units i}
+
            {FOREACH units i}
[switch]            #Check the resistances
+
            [switch]            #Check the resistances
variable=weapon.type
+
                variable=weapon.type
[case]
+
                [case]
value=arcane
+
                    value=arcane
    {VARIABLE_OP healed_amount add "$($units[$i].resistance.arcane*$weapon.damage)"}
+
                        {VARIABLE_OP healed_amount add "$($units[$i].resistance.arcane*$weapon.damage)"}
[/case]
+
                [/case]
[case]
+
                [case]
value=fire
+
                    value=fire
    {VARIABLE_OP healed_amount add "$($units[$i].resistance.fire*$weapon.damage)"}
+
                        {VARIABLE_OP healed_amount add "$($units[$i].resistance.fire*$weapon.damage)"}
[/case]
+
                [/case]
[case]
+
                [case]
value=cold
+
                    value=cold
    {VARIABLE_OP healed_amount add "$($units[$i].resistance.cold*$weapon.damage)"}
+
                        {VARIABLE_OP healed_amount add "$($units[$i].resistance.cold*$weapon.damage)"}
[/case]
+
                [/case]
[case]
+
                [case]
value=blade
+
                    value=blade
    {VARIABLE_OP healed_amount add "$($units[$i].resistance.blade*$weapon.damage)"}
+
                        {VARIABLE_OP healed_amount add "$($units[$i].resistance.blade*$weapon.damage)"}
[/case]
+
                [/case]
[case]
+
                [case]
value=pierce
+
                    value=pierce
    {VARIABLE_OP healed_amount add "$($units[$i].resistance.pierce*$weapon.damage)"}
+
                        {VARIABLE_OP healed_amount add "$($units[$i].resistance.pierce*$weapon.damage)"}
[/case]
+
                [/case]
[case]
+
                [case]
value=impact
+
                    value=impact
    {VARIABLE_OP healed_amount add "$($units[$i].resistance.impact*$weapon.damage)"}
+
                        {VARIABLE_OP healed_amount add "$($units[$i].resistance.impact*$weapon.damage)"}
[/case]
+
                [/case]
  [/switch]
+
            [/switch]
{NEXT i}
+
            {NEXT i}
[store_unit]       #Float the healed amount over the unit, like if it had drained
+
            [store_unit]       #Float the healed amount over the unit, like if it had drained
[filter]    #Two numbers will float, the one from the regular hit and one from this
+
                [filter]    #Two numbers will float, the one from the regular hit and one from this
x,y=$x1,$y1
+
                x,y=$x1,$y1
[/filter]
+
                [/filter]
kill=no
+
                kill=no
variable=FLOATING_TEXT_temp
+
                variable=FLOATING_TEXT_temp
[/store_unit]
+
            [/store_unit]
[unstore_unit]
+
            [unstore_unit]
variable=FLOATING_TEXT_temp
+
                variable=FLOATING_TEXT_temp
find_vacant=no
+
                find_vacant=no
red,green,blue=0,255,0
+
                red,green,blue=0,255,0
text=$($healed_amount/200)        #Operating with huge numbers because rounding is a problem
+
                text=$($healed_amount/200)        #Operating with huge numbers because rounding is a problem
[/unstore_unit]
+
            [/unstore_unit]
{CLEAR_VARIABLE FLOATING_TEXT_temp}
+
            {CLEAR_VARIABLE FLOATING_TEXT_temp}
[heal_unit]
+
            [heal_unit]
[filter]
+
                [filter]
x,y=$x1,&y1
+
                    x,y=$x1,&y1
[/filter]
+
                [/filter]  
amount=$($healed_amount/200)
+
                amount=$($healed_amount/200)
animate=no
+
                animate=no
[/heal_unit]
+
            [/heal_unit]
{CLEAR_VARIABLE units}
+
        {CLEAR_VARIABLE units,healed_amount}
{CLEAR_VARIABLE healed_amount}
+
        [/else]
[/else]
+
    [/if]
[/if]
+
    [harm_unit]
[harm_unit]
+
        [filter]
[filter]
+
            [filter_adjacent]
[filter_adjacent]
+
                x,y=$x1,$y1
x,y=$x1,$y1
+
            [/filter_adjacent]
[/filter_adjacent]
+
            [not]
[not]
+
                side=1             #If you want to use it in an era, use side=$unit.side instead
side=1             #If you want to use it in an era, use side=$unit.side instead
+
            [/not]
[/not]
+
            [not]             #If you want to use it in an era, use side=$unit.side instead
[not]             #If you want to use it in an era, use side=$unit.side instead
+
                x,y=$x2,$y2
x,y=$x2,$y2
+
            [/not]
[/not]
+
        [/filter]
[/filter]
+
        [filter_second]
[filter_second]
+
            x,y=$x1,$y1
x,y=$x1,$y1
+
        [/filter_second]
[/filter_second]
+
        amount=$weapon.damage
amount=$weapon.damage
+
        damage_type=$weapon.type
damage_type=$weapon.type
+
        fire_event=yes
fire_event=yes
+
        experience=yes      #You will have to think about this
experience=yes      #You will have to think about this
+
        poisoned=$has_poison  #We have detected these two effects before
poisoned=$has_poison  #We have detected these two effects before
+
        slowed=$has_slow
slowed=$has_slow
+
    [/harm_unit]  
[/harm_unit]  
+
    {CLEAR_VARIABLE has_slow,has_poison,has_drain}
{CLEAR_VARIABLE has_slow}
 
{CLEAR_VARIABLE has_poison}
 
{CLEAR_VARIABLE has_drain}
 
 
  [/event]
 
  [/event]
 +
</syntaxhighlight>
  
 
== See Also ==
 
== See Also ==

Revision as of 11:20, 13 September 2022

Remember that you must include the WML ability code in every scenario where you intend them to work. Or include them in the unit file inside the [unit_type] tag.

Some abilities require macros from Utilities.


Knockback

When a unit is hit with a knockback attack, it is immediately pushed back one hex away from the attacker. Units cannot be knocked back into an occupied hex, out of villages or onto terrain they normally could not move to. Only works on offense.

Use this to display the special correctly on the attacks you want:

#define WEAPON_SPECIAL_KNOCKBACK
    [dummy]
        id=knockback
        name= _ "knockback"
        female_name= _ "female^knockback"
        description=_ "When a unit is hit with a knockback attack, it is immediately pushed back one hex away from the attacker. Units cannot be knocked back into an occupied hex, out of villages or onto terrain they normally could not move to. Only works on offense."
    [/dummy]
#enddef

And insert this event to your [scenario], [multiplayer], [unit_type] or [era]:

[event]
    name=attacker hits
    first_time_only=no

    [filter_attack]
        special_id=knockback
    [/filter_attack]

    [filter_second]
        [not]
            [filter_location]
                terrain=*^V*
            [/filter_location]
        [/not]
    [/filter_second]

    [if]
        [variable]
            name=second_unit.hitpoints
            greater_than=0
        [/variable]

            [store_locations]
                [not]
                    [filter]
                    [/filter]
                [/not]

                [filter_adjacent_location]
                    x,y=$x2,$y2
                    adjacent=-$unit.facing
                [/filter_adjacent_location]

                variable=knockback_target_hex
            [/store_locations]

            [if]
                [variable]
                    name=knockback_target_hex.length
                    greater_than=0
                [/variable]

                [then]
                    [teleport]
                        [filter]
                            x,y=$x2,$y2
                        [/filter]

                        x,y=$knockback_target_hex.x,$knockback_target_hex.y
                        ignore_passability=no
                    [/teleport]

                    [if]
                        [have_unit]
                            x,y=$knockback_target_hex.x,$knockback_target_hex.y
                        [/have_unit]

                        [then]
                            [sound]
                                name=fist.ogg
                            [/sound]

                            # the knockbacked unit doesn't seem to receive experience by default,
                            # so we need to add it manually
                            [store_unit]
                                [filter]
                                    x,y=$knockback_target_hex.x,$knockback_target_hex.y
                                [/filter]

                                kill=yes
                                variable=knockbacked
                            [/store_unit]

                            {VARIABLE_OP knockbacked.experience add $unit.level}

                            [unstore_unit]
                                variable=knockbacked
                                text= _ "knockback"
                                {COLOR_HARM}
                                advance=true
                            [/unstore_unit]

                            {CLEAR_VARIABLE knockbacked}
                        [/then]
                    [/if]
                [/then]
            [/if]

            {CLEAR_VARIABLE knockback_direction,knockback_target_hex}
        [/then]
    [/if]
[/event]

Charm

When a unit is hit with a charm attack, it instantly jumps to the attacker's side, and returns to it's original side at the beginning of that side's turn. A charmed unit has 1 movement point and can attack.

Example that makes all Troll Whelps have charm on their attack:

{CHARM (type=Troll Whelp) fist}
#define CHARM FILTER WEAPON
[event]
        name=attacker_hits
        first_time_only=no

        [filter]
            {FILTER}
        [/filter]

        [special_filter]
            weapon={WEAPON}
        [/special_filter]

        {STORE_UNIT_VAR x,y=$x1,$y1 side charmer_side}
        {STORE_UNIT_VAR x,y=$x2,$y2 side charmed_side}

        {IF_VAR charmer_side not_equals $charmed_side (
            [then]
                {MODIFY_UNIT x,y=$x2,$y2 variables.real_side $charmed_side}
                {MODIFY_UNIT x,y=$x2,$y2 side $charmer_side}
                {MODIFY_UNIT x,y=$x2,$y2 moves 1}
                {MODIFY_UNIT x,y=$x2,$y2 attacks_left 1}

                {VARIABLE_OP varname format "side_$charmed_side|_units_charmed"}
                {VARIABLE $varname yes}

                {CLEAR_VARIABLE varname}
            [/then]
        )}

        {CLEAR_VARIABLE charmer_side,charmed_side}
    [/event]

    [event]
        name=side turn
        first_time_only=no

        {VARIABLE_OP this_side_charmed to_variable "side_$side_number|_units_charmed"}

        {IF_VAR this_side_charmed equals yes (
            [then]
                [store_unit]
                    [filter]
                        [not]
                            side=$side_number
                        [/not]
                    [/filter]

                    variable=possibly_charmed
                    kill=no
                [/store_unit]

                {FOREACH possibly_charmed i}
                    {VARIABLE_OP real_side format "0$possibly_charmed[$i].variables.real_side"}

                    {IF_VAR real_side not_equals "0" (
                        [then]
                            {IF_VAR side_number equals $possibly_charmed[$i].variables.real_side (
                                [then]
                                    {CLEAR_VARIABLE possibly_charmed[$i].variables.real_side}
                                    {VARIABLE possibly_charmed[$i].side $side_number}

                                    [unstore_unit]
                                        variable=possibly_charmed[$i]
                                        find_vacant=no
                                    [/unstore_unit]
                                [/then]
                            )}
                        [/then]
                    )}
                {NEXT i}

                {CLEAR_VARIABLE possibly_charmed}
            [/then]
        )}
    [/event]
#enddef

Bloodlust

Bloodlust is a very simple ability. If a unit that has bloodlust kills an enemy unit when attacking, it may attack again, provided that there are more enemy units adjacent to it.

This would give the bloodlust ability to all Dwarvish Ulfserkers (making them insanely powerful):

{BLOODLUST (type=Dwarvish Ulfserker)}
#define BLOODLUST FILTER
    [event]
        name=die
        first_time_only=no

        [filter_second]
            {FILTER}
        [/filter_second]

        {MODIFY_UNIT x,y=$x2,$y2 moves 0}
        {MODIFY_UNIT x,y=$x2,$y2 attacks_left 1}
    [/event]
#enddef

Pickpocket

This special could also be called loot. When a unit with this attack special sucessfully hits an enemy unit, it gains a certain amount of gold.

To do this, use this code:

#define WEAPON_SPECIAL_PICKPOCKET
    # Canned definition of the pickpocket ability to be included in a
    # [specials] clause.
    # dummy weapon special used to describe the effect to the user
    # and filter on special's id
    [dummy]
        id=weapon_pickpocket
        name= _ "pickpocket"
        description= _ "Gain money for attacking your foe. Each strike scores you one gold."
        apply_to=opponent
    [/dummy]
[/specials]
[/attack]

    # event that creates a "pickpocket has worked" variable
    # and sets it to "yes" if the attacker hits at least once.
    [event]
        name=attacker_hits
        first_time_only=no
        [filter_attack]
            special_id=weapon_pickpocket
        [/filter_attack]   
        [store_unit]
            [filter]
                x,y=$x1,$y1
            [/filter]
            variable=unit_att_with_pickpocket
            mode=append
        [/store_unit]
        [set_variable]
            name=unit_att_with_pickpocket.variables.pickpocket_has_worked
            value=yes
        [/set_variable]
        [unstore_unit]
            variable=unit_att_with_pickpocket
        [/unstore_unit]   
            {CLEAR_VARIABLE unit_att_with_pickpocket}
    [/event]
    [event]
        name=attacker_hits
        first_time_only=no  
        [filter_attack]
            special_id=weapon_pickpocket
        [/filter_attack]   
        [store_unit]
            [filter]
                x,y=$x1,$y1
            [/filter]
            variable=pickpocketer
            mode=append
        [/store_unit]   
        [store_unit]
            [filter]
                x,y=$x2,$y2
            [/filter]
            variable=pickpocketed
            mode=append
        [/store_unit]   
        [if]
            [variable]
                name=pickpocketer.variables.pickpocket_has_worked
                boolean_equals=yes
            [/variable]
            [then]
                [gold]
                    side=$side_number
                    amount=2
                [/gold]
                [unstore_unit]
                    variable=pickpocketed
                    text="!"
                    {COLOR_HEAL}
                [/unstore_unit]
            [/then]
        [/if]   
        {CLEAR_VARIABLE pickpocketer,pickpocketed}
    [/event]
    [+attack]
    [+specials]
#enddef

It can be placed after the [unit_type] tag, or in its own .cfg file.


To change the amount of gold given per hit, change

[gold]
    side=$side_number
    amount=X
[/gold]

Where X is the amount of gold you want.


If you want the gold to be constant, given at the end of the turn if at least one of the attack hits, instead of X amount of gold per hit, change

[event]
    name=attacker_hits
    first_time_only=no

to

[event]
   name=attack_end
   first_time_only=no

Soultaker

Any unit with this ability will gain an additional point of damage per strike every time it kills an enemy. Coder(s) unknown, made for Melon's Youkai faction (https://r.wesnoth.org/t20100).

To give a unit the ability, place the following in any .cfg file loaded by the campaign or era:

#define ABILITY_SOULTAKER
   [dummy]
       id=soultaker
       name= _ "soultaker"
       description=_ "This unit gains an additional point added to its melee damage whenever it kills a living unit."
   [/dummy]
[/abilities]

[event]
    name=die
    first_time_only=no
    [filter]
        [not]
            status=not_living
        [/not]
    [/filter]

    [filter_second]
        ability=soultaker
    [/filter_second]

    [unstore_unit]
        variable=second_unit
        {COLOR_HEAL}
        text= _ "+1 damage"
    [/unstore_unit]

    [object]
        silent=yes
        duration=forever
        [filter]
            x,y=$x2,$y2
        [/filter]

        [effect]
            apply_to=attack
            range=melee
            increase_damage=1
        [/effect]
    [/object]
[/event]

[+abilities]
#enddef

And the following in the unit's [abilities] tag:

{ABILITY_SOULTAKER}

Soultaker (weapon special)

Unit with this weapon special will gain an additional point of damage per strike for that weapon every time it kills an enemy with this attack. Coder Ravana, made for ageless era (https://r.wesnoth.org/t25274) based on previous ability.

To give a unit the weapon special, load the following code:

#define WEAPON_SPECIAL_SOULTAKER
    [dummy]
        id=soultaker
        name= _ "soultaker"
        description=_"This unit gains an additional point added to its damage whenever it kills a living unit."
    [/dummy]
[/specials]
[/attack]

[event]
    name=die
    first_time_only=no
    id=soultaker_event
    [filter]
        [not]
            status=not_living
        [/not]
    [/filter]
    [filter_second_attack]
        special_id=soultaker
    [/filter_second_attack]
    [unstore_unit]
        variable=second_unit
        {COLOR_HEAL}
        text= _ "+1 damage"
    [/unstore_unit]
    [object]
        silent=yes
        duration=forever
        [filter]
            x,y=$x2,$y2
        [/filter]
        [effect]
            apply_to=attack
            name=$second_weapon.name
            increase_damage=1
        [/effect]
    [/object]
[/event]
[+attack]
    [+specials]
#enddef


And the following in the attack's [specials] tag:

{WEAPON_SPECIAL_SOULTAKER}

Charm (Type 2)

An attack special. If the attack hits, and the target is level 0 or 1, the target is converted to the attacker's side. However, if it misses, the attacker is converted to the defender's side. Maintainer is krotop, using 1.6.x syntax (and compatible with 1.7.x], made for Melon's Youkai faction (https://r.wesnoth.org/t22539)


    #define WEAPON_SPECIAL_CHARM
    # Canned definition of the Charm ability to be included in a
    # [specials] clause.

    # dummy weapon special used to describe the effect to the user
    # and filter on special's id
    [dummy]
        id=weapon_charm
        name= _ "charm"
        description= _ "Turns a living level 1 or level 0 unit to your side. Beware  if all of your attacks miss, the charm user turns to the defender side, even if it is your leader. You can not charm an ennemy leader or a non-living creature." 
        apply_to=opponent
    [/dummy]

    [/specials]
    [/attack]

    # event that creates a variable at the beginning of the fight to check if the attacker hit at least once by the end.
    [event]
        name=attack
        first_time_only=no
        
        [filter_attack]
            special_id=weapon_charm
        [/filter_attack]
        
        [store_unit]
            [filter]
                x,y=$x1,$y1
            [/filter]
            variable=unit_att_with_charm
            mode=append
        [/store_unit]   
        [set_variable]
            name=unit_att_with_charm.variables.charm_has_worked
            value=no
        [/set_variable] 
        [unstore_unit]
            variable=unit_att_with_charm
        [/unstore_unit]
        
        {CLEAR_VARIABLE unit_att_with_charm}
    [/event]

    # event that creates a "charm has worked" variable
    # and sets it to "yes" if the attacker hits at least once.
    [event]
        name=attacker_hits
        first_time_only=no
        
        [filter_attack]
            special_id=weapon_charm
        [/filter_attack]
        
        [store_unit]
            [filter]
                x,y=$x1,$y1
            [/filter]
            variable=unit_att_with_charm
            mode=append
        [/store_unit]
        [set_variable]
            name=unit_att_with_charm.variables.charm_has_worked
            value=yes
        [/set_variable]
        [unstore_unit]
            variable=unit_att_with_charm
        [/unstore_unit]
        
        {CLEAR_VARIABLE unit_att_with_charm}
    [/event]

    # event that shifts a unit to the other side
    # if the defending unit
    #       - was not lvl1 or lvl0 
    #       - and was not a recruiting unit 
    #       - and was a not a "non-living" creature
    # then :
    # -> if the attacker missed all attacks, it goes to the defender side.
    # -> if the attacker hit once at least, the defender goes to the attacker side.
    [event]
        name=attack_end
        first_time_only=no
        
        [filter_attack]
            special_id=weapon_charm
        [/filter_attack]
        [filter_second]
            canrecruit=no
            [and]
                level=0
                [or]
                    level=1
                [/or]
            [/and]
            [and]
                [not]
                     status=not_living
                [/not]
            [/and]
        [/filter_second]
        
        [store_unit]
            [filter]
                x,y=$x1,$y1
            [/filter]
            variable=charmer
            mode=append
        [/store_unit]
        
        [store_unit]
            [filter]
                x,y=$x2,$y2
            [/filter]
            variable=charmed
            mode=append
        [/store_unit]
        
        [if]
            [variable]
                name=charmer.variables.charm_has_worked
                boolean_equals=no
            [/variable]
            [then]
                [set_variable]
                    name=charmer.side
                    value=$charmed.side
                [/set_variable]
                [unstore_unit]
                    variable=charmer
                    text="Charm failed!"
                    {COLOR_HARM}
                [/unstore_unit]
            [/then]
            [else]
                [set_variable]
                    name=charmed.side
                    value=$charmer.side
                [/set_variable]
                [unstore_unit]
                    variable=charmed
                    text="Charmed!"
                    {COLOR_HEAL}
                [/unstore_unit]
            [/else]
        [/if]

        {CLEAR_VARIABLE charmer,charmed}
    [/event]

    [+attack]
    [+specials]
#enddef

Works

Unit with ability works will produce 1 gold per turn.

Put this macro into you code before the last piece of code.

#define ABILITY_WORKS
    [leadership]
        value=0
        id=peasant_works
        cumulative=no
        name="works"
        description= _ "This unit produces 1 gold per turn."
    [/leadership]
#enddef

Put this event into your code.

[event]
    name=side turn
    first_time_only=no
    [store_unit]
        [filter]
            # your filter here... for example type=Peasant
        [/filter]
        variable=worker
    [/store_unit]

        {FOREACH worker i}
    
            [gold]
                side=$side_number 
                amount=1
            [/gold] 
            [unstore_unit]
                variable=worker[$i]
                text="1"
                red,green,blue=255,255,0 
            [/unstore_unit]
                
        {NEXT i}
    
    {CLEAR_VARIABLE worker}
[/event]

And give the unit the ability like this

[object]
    silent=yes
    [effect]
        apply_to=new_ability
        [abilities]
            {ABILITY_WORKS}
        [/abilities]
     [/effect]
 [/object]

Mind Flay

The weapon special gives an attacker 1 point of exp taken from a defender for each hit. This will violate minimum experience (i.e. defender can go below 0).

Give this special to the attack(s) you want it to have.

#define WEAPON_SPECIAL_MIND_FLAY
    [mindflay]
        id=mind_flay
        name="Mind Flay"
        description="When used offensively, each hit of the mind flay attack takes 1 point of experience from the defender and gives it to the attacker."
    [/mindflay]
#enddef


Include these events into your scenario.

[event]
    name=attack
    first_time_only=no
    [special_filter]
        weapon=mind flay
    [/special_filter]
    {VARIABLE hit_number 0}
[/event]
[event]
    name=attacker_hits
    first_time_only=no
    [special_filter]
        weapon=mind flay
    [/special_filter]
    {VARIABLE_OP hit_number add 1}
[/event]
[event]
    name=attack_end
    first_time_only=no
    [special_filter]
        weapon=mind flay
    [/special_filter]
    {VARIABLE_OP second_unit.experience add -$hit_number}
    {VARIABLE_OP unit.experience add $hit_number}
    [unstore_unit]
        variable=unit
        find_vacant=no
        text=$hit_number
        blue=255
    [/unstore_unit]
    [unstore_unit]
        variable=second_unit
        find_vacant=no
    [/unstore_unit]
    {CLEAR_VARIABLE hit_number}
[/event]

Note: In dev version substitute "name=" instead of "weapon=".

Initiative

Initiative is an aura ability. Much like Leadership, it affects adjacent allies but not the unit itself.

#define AURA_INITIATIVE TYPE
    [dummy]
        id=initiative
        name= _ "initiative"
        description= _ "Adjacent allies are granted Firststrike with all weapons."
    [/dummy]
[/abilities]

    [event]
        name=attack
        first_time_only=no
 
        [filter]
            [filter_adjacent]
                type={TYPE}
                is_enemy=no
            [/filter_adjacent]
        [/filter]
        
        {FOREACH unit.attack i}
            {VARIABLE unit.attack[$i].specials.firststrike.id "firststrike"}
        {NEXT i}
        
        [unstore_unit]
            variable=unit
        [/unstore_unit]
    [/event]
    [event]
        name=attack
        first_time_only=no
 
        [filter_second]
            [filter_adjacent]
                type={TYPE}
                is_enemy=no
            [/filter_adjacent]
        [/filter_second]
        
        {FOREACH second_unit.attack i}
            {VARIABLE second_unit.attack[$i].specials.firststrike.id "firststrike"}
        {NEXT i}
        
        [unstore_unit]
            variable=second_unit
        [/unstore_unit]
    [/event]
    [event]
        name=attack_end
        first_time_only=no
 
        [filter]
            [wml_filter]
                [attack]
                    [specials]
                        [firststrike]
                            id=firststrike
                        [/firststrike]
                    [/specials]
                [/attack]
            [/wml_filter]
        [/filter]
        
        {FOREACH unit.attack i}
            {CLEAR_VARIABLE unit.attack[$i].specials.firststrike}
        {NEXT i}
        
        [unstore_unit]
            variable=unit
        [/unstore_unit]
    [/event]
    [event]
        name=attack_end
        first_time_only=no
 
        [filter_second]
            [wml_filter]
                [attack]
                    [specials]
                        [firststrike]
                            id=firststrike
                        [/firststrike]
                    [/specials]
                [/attack]
            [/wml_filter]
        [/filter_second]
        
        {FOREACH second_unit.attack i}
            {CLEAR_VARIABLE second_unit.attack[$i].specials.firststrike}
        {NEXT i}
        
        [unstore_unit]
            variable=second_unit
        [/unstore_unit]
    [/event]
[+abilities]
#enddef

A WML filter may be added instead of the type if you want some units of that type to not have the ability.

Blitz

Blitz is an aura ability. Much like Leadership, it affects adjacent allies but not the unit itself.

#define AURA_BLITZ TYPE
    [dummy]
        id=blitz    
        name= _ "blitz"
        description= _ "Allies that start their turn adjacent to this unit are granted Skirmisher for that turn."
    [/dummy]
[/abilities]

    [event]
        name=side turn
        first_time_only=no
        
        [store_unit]
            [filter]
                [wml_filter]
                    blitzed=1
                [/wml_filter]
            [/filter]
            variable=blitz_refresh
        [/store_unit]
        
        {FOREACH blitz_refresh i}
            {CLEAR_VARIABLE blitz_refresh[$i].abilities.skirmisher}
            {VARIABLE blitz_refresh[$i].blitzed 0}
            [unstore_unit]
                variable=blitz_refresh[$i]
            [/unstore_unit]
        {NEXT i}
 
        [store_unit]
            [filter]
                side=$side_number
                [filter_adjacent]
                    type={TYPE}
                    is_enemy=no
                [/filter_adjacent]
            [/filter]
            variable=blitzed
        [/store_unit]
        
        {FOREACH blitzed i}
            [if]
                [variable]
                    name=blitzed[$i].abilities.skirmisher.id
                    not_equals="skirmisher"
                [/variable]
                [then]
                    {VARIABLE blitzed[$i].blitzed 1}
                    {VARIABLE blitzed[$i].abilities.skirmisher.id skirmisher}
                    {VARIABLE blitzed[$i].abilities.skirmisher.name "skirmisher"}
                    {VARIABLE blitzed[$i].abilities.skirmisher.description  "This unit is skilled in moving past enemies quickly, and ignores all enemy Zones of Control."}
                    [unstore_unit]
                        variable=blitzed[$i]
                    [/unstore_unit]
                [/then]
            [/if]
        {NEXT i}
    [/event]
[+abilities]
#enddef

Immune to drain or plague or poison

This macro will grant immunity to drain for a unit. By changing a few specials' names and ability names, you can easily expand it for an immunity to plague or drain. This will not work properly if there is a unit with multiple weapon specials that might be affected (plague+drain, poison+plague, poison+drain, poison+drain+plague), in this case, it will grant immunity to all of them.

#define ABILITY_UNDRAINABLE
#This is the ability tagging the unit for the events. Use it as an ability.
  [dummy]
      id=undrainable
      name= _ "undrainable"
      description= _ "this unit is cannot be drained.
It will still be damaged by draining attacks, but the enemy will not gain any HP."
  [/dummy]
#enddef

#define UNDRAINABLE
#Place those in every scenario (or era) where these units will appear.
#It makes the unit undead for the time of the attack (it cannot be seen),
#if the particular weapon special was used.
  [event]
      name=attack
      first_time_only=no
     [filter_attack]
         special=drains
     [/filter_attack]
     [filter_second]
         ability=undrainable
     [/filter_second]
         [modify_unit]
        [filter]
            x,y=$x2,$y2
        [/filter]
            [status]
           not_living=yes
            [/status]
         [/modify_unit]
  [/event]

  [event]
      name=attack_end
      first_time_only=no
     [filter_attack]
         special=drains
     [/filter_attack]
     [filter_second]
         ability=undrainable
     [/filter_second]
         [modify_unit]
        [filter]
            x,y=$x2,$y2
        [/filter]
            [status]
           not_living=no
            [/status]
         [/modify_unit]
  [/event]

  [event]
      name=attack
      first_time_only=no
     [filter_second_attack]
         special=drain
     [/filter_second_attack]
     [filter]
         ability=undrainable
     [/filter]
         [modify_unit]
        [filter]
            x,y=$x1,$y1
        [/filter]
            [status]
           not_living=yes
            [/status]
         [/modify_unit]
  [/event]

  [event]
      name=attack_end
      first_time_only=no
     [filter_second_attack]
         special=drain
     [/filter_second_attack]
     [filter]
         ability=undrainable
     [/filter]
         [modify_unit]
        [filter]
            x,y=$x1,$y1
        [/filter]
            [status]
           not_living=no
            [/status]
         [/modify_unit]
  [/event]
#enddef

A WML filter may be added instead of the type if you want some units of that type to not have the ability.

Whirlwind Attack

This attack is supposed to be an attack when you spin with your weapons in arms, hitting all nearby enemies, while they cannot counter. It should be used with the magical weapon special, because the spinning weapons are not easy to dodge and the player would pick to attack the unit with the lowest defence without it. It works with drain, slow and poison weapon specials. The attack is supposed to be attack-only, but it can be easily edited to work also on defence.

This is a pair of two macros, one is a weapon special that makes the enemy unable to counter (lowers the number of attacks by 10; for the case if there was a boss or something). The other one is an event that damages the units, that should be placed into every scenario where the unit appears (or the era), preferably through a macro.

This is the part that is the weapon special that marks it.

[attacks]      #This can be changed to a dummy tag if you don't want it to do anything.
    id=whirlwind
    name= _ "whirlwind"
    description= _ "When this attack is used, all units adjacent the attacker take the damage, and cannot be countered."
    value=0
    apply_to=opponent
[/attacks]


This is the event.

[event]
   name=attacker_hits
   first_time_only=no
   [filter_attack]
       special_id=whirlwind
   [/filter_attack]
   {VARIABLE has_drain 0}      # Notifies the weapon specials
   {VARIABLE has_slow no}
   {VARIABLE has_poison no}
   {FOREACH weapon.specials.damage i}
   [if]
       [variable]
           name=weapon.specials.drains.id
           equals=drains
       [/variable]
       [then]
           {VARIABLE has_drain 1}

       [/then]
   [/if]
   {NEXT i}
   [if]
       [variable]
           name=weapon.specials.poison.id
           equals=poison
       [/variable]
       [then]
           {VARIABLE has_poison yes}

       [/then]
   [/if]
   [if]
       [variable]
           name=weapon.specials.slow.id
           equals=slow
       [/variable]
       [then]
           {VARIABLE has_slow yes}

       [/then]
   [/if]
   [if]
       [variable]
           name=has_drain
           equals=0
       [/variable]
       [else]
           [store_unit]        #We need to know how many units were drained, and what were their resistances
               [filter]
                   [filter_adjacent]
                       x,y=$x1,$y1
                   [/filter_adjacent]
                   [not]
                       side=1              #If you want to use it in an era, use side=$unit.side instead
                   [/not]
                   [not]         #The target unit is already hit by the attack
                       x,y=$x2,$y2
                   [/not]
                   [not]          #Undead are undrainable
                       race=undead
                   [/not]
               [/filter]
               variable=units
           [/store_unit]  
           {VARIABLE healed_amount 0}
           {FOREACH units i}
           [switch]            #Check the resistances
               variable=weapon.type
               [case]
                   value=arcane
                       {VARIABLE_OP healed_amount add "$($units[$i].resistance.arcane*$weapon.damage)"}
               [/case]
               [case]
                   value=fire
                       {VARIABLE_OP healed_amount add "$($units[$i].resistance.fire*$weapon.damage)"}
               [/case]
               [case]
                   value=cold
                       {VARIABLE_OP healed_amount add "$($units[$i].resistance.cold*$weapon.damage)"}
               [/case]
               [case]
                   value=blade
                       {VARIABLE_OP healed_amount add "$($units[$i].resistance.blade*$weapon.damage)"}
               [/case]
               [case]
                   value=pierce
                       {VARIABLE_OP healed_amount add "$($units[$i].resistance.pierce*$weapon.damage)"}
               [/case]
               [case]
                   value=impact
                       {VARIABLE_OP healed_amount add "$($units[$i].resistance.impact*$weapon.damage)"}
               [/case]
           [/switch]
           {NEXT i}
           [store_unit]        #Float the healed amount over the unit, like if it had drained
               [filter]    #Two numbers will float, the one from the regular hit and one from this
               x,y=$x1,$y1
               [/filter]
               kill=no
               variable=FLOATING_TEXT_temp
           [/store_unit]
           [unstore_unit]
               variable=FLOATING_TEXT_temp
               find_vacant=no
               red,green,blue=0,255,0
               text=$($healed_amount/200)         #Operating with huge numbers because rounding is a problem
           [/unstore_unit]
           {CLEAR_VARIABLE FLOATING_TEXT_temp}
           [heal_unit]
               [filter]
                   x,y=$x1,&y1
               [/filter]   
               amount=$($healed_amount/200)
               animate=no
           [/heal_unit]
       {CLEAR_VARIABLE units,healed_amount}
       [/else]
   [/if]
   [harm_unit]
       [filter]
           [filter_adjacent]
               x,y=$x1,$y1
           [/filter_adjacent]
           [not]
               side=1             #If you want to use it in an era, use side=$unit.side instead
           [/not]
           [not]             #If you want to use it in an era, use side=$unit.side instead
               x,y=$x2,$y2
           [/not]
       [/filter]
       [filter_second]
           x,y=$x1,$y1
       [/filter_second]
       amount=$weapon.damage
       damage_type=$weapon.type
       fire_event=yes
       experience=yes      #You will have to think about this
       poisoned=$has_poison   #We have detected these two effects before
       slowed=$has_slow
   [/harm_unit] 
   {CLEAR_VARIABLE has_slow,has_poison,has_drain}
[/event]

</syntaxhighlight>

See Also