WML Abilities

From The Battle for Wesnoth Wiki
Revision as of 15:56, 10 January 2009 by Jequ (talk | contribs) (works ability)

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] tag.

Some abilities require macros from Utilities.

Knockback

When a unit is hit with a knockback attack, it is immediately pushed one hex away from the attacker, at which point the combat ends. Exception: units in villages can't be knocked out of them.

Examples that give knockback for every Drake Glider on their slam attack, and for the Shock Trooper named Jane:

{KNOCKBACK (type=Drake Glider) slam}
{KNOCKBACK description=Jane mace}

Requires the macro OPPOSITE_SIDE.

#define KNOCKBACK FILTER WEAPON
    [event]
        name=attacker_hits
        first_time_only=no

        [filter]
            {FILTER}
        [/filter]

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

        [sound]
            name=ghoul-hit.wav
        [/sound]

        {OPPOSITE_SIDE $x2 $y2 $x1 $y1 target_hex}

        [store_locations]
            x,y=$x2,$y2
            terrain=AaBbDeLptUVvYZ
            variable=defender_in_village
        [/store_locations]
        [if]
            [have_unit]
               x,y=$target_hex.x,$target_hex.y
            [/have_unit]
            [else]
                {IF_VAR defender_in_village.length not_equals 1 (
                    [then]
                        {STORE_UNIT_VAR x,y=$x2,$y2 side side_of_defender}

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

                            x,y=$target_hex.x,$target_hex.y
                        [/teleport]

                        [capture_village]
                            side=$side_of_defender
                            x,y=$target_hex.x,$target_hex.y
                        [/capture_village]

                        {CLEAR_VARIABLE side_of_defender}
                    [/then]
                )}
            [/else]
        [/if]

        {CLEAR_VARIABLE target_hex}
        {CLEAR_VARIABLE defender_in_village}
    [/event]
#enddef

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}
        {CLEAR_VARIABLE 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 - say 10.

To do this, use this code:

#define WEAPON_SPECIAL_PICKPOCKET
    [damage]
        id=pickpocket
        name="Pickpocket"
        description="When used offensively, this attack gives 10 gold to the attacker on every successful hit." 
        multiply=1
    [/damage]
#enddef

Then put this event in your scenario:

[event]
    name=attacker_hits
    first_time_only=no
    [filter]
        side=$side_number
	 canrecruit=yes
    [/filter]
    [special_filter]
        weapon=pickpocket gloves
    [/special_filter]
    [gold]
        side=$side_number
	 amount=10
    [/gold]
[/event]

Then give the unit you want to have the "pickpocket" special something like this:

[object]
    silent=yes
    [effect]
        apply_to=new_attack 
	 name=pickpocket gloves
	 type=impact
	 range=melee 
	 damage=3
	 number=3 
	 [specials]
	     {WEAPON_SPECIAL_PICKPOCKET}
	 [/specials]
    [/effect]
[/object]

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).

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=_ "Soultaker:
This unit gains an additional point added to its maximum damage whenever it kills a living unit."
	[/dummy]

[/abilities]
[event]
	name=die
	first_time_only=no
	[filter]
		[not]
			[wml_filter]
				[status]
					not_living="yes"
				[/status]
			[/wml_filter]
		[/not]
	[/filter]

	[filter_second]
		ability=soultaker
	[/filter_second]

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

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

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

[+abilities]
#enddef

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

	{ABILITY_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.4.X syntax, made for Melon's Youkai faction (http://www.wesnoth.org/forum/viewtopic.php?f=21&t=22539)

#define ABILITY_CHARM WEAPON
# dummy ability, defining the ability id for the next filters
[dummy]
	id=charm_attack
[/dummy]

[/abilities]



# 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]
		ability=charm_attack
	[/filter]
	[special_filter]
		weapon={WEAPON}
	[/special_filter]
	
	[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]
		ability=charm_attack
	[/filter]
	[special_filter]
		weapon={WEAPON}
	[/special_filter]
	
	[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]
		ability=charm_attack
	[/filter]
	[special_filter]
		weapon={WEAPON}
	[/special_filter]
	[filter_second]
		canrecruit=no
		[and]
			level=0
			[or]
			level=1
			[/or]
		[/and]
		[and]
			[not]
			[wml_filter]
				[status]
					not_living=yes
				[/status]
			[/wml_filter]
			[/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
			equals=no
		[/variable]
		[then]
			[set_variable]
				name=charmer.side
				value=$charmed.side
			[/set_variable]
		[/then]
		[else]
			[set_variable]
				name=charmed.side
				value=$charmer.side
			[/set_variable]
		[/else]
	[/if]

	[unstore_unit]
		variable=charmer
	[/unstore_unit]
	[unstore_unit]
		variable=charmed
	[/unstore_unit]
	
	{CLEAR_VARIABLE charmer}
	{CLEAR_VARIABLE charmed}
	
[/event]

[+abilities]

#enddef




#define WEAPON_SPECIAL_CHARM
# dummy weapon special used to describe the effect to the user

[damage]
	id=weapon_charm
	name= _ "charm"
	name_inactive= _ "charm"
	description= _ "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." 
	description_inactive= _ "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." 
	apply_to=opponent
[/damage]

#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= _ "Works:
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
		kill=no
	[/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]

See Also