Difference between revisions of "AnimationWML"

From The Battle for Wesnoth Wiki
m
(Remove DvFeture, highlight tags)
Line 3: Line 3:
 
== Animation and sound ==
 
== Animation and sound ==
  
Several key/tags of the ''[unit]'' and ''[attack]'' tags do not affect gameplay, but are available to control the way units and their attacks will be animated and heard.
+
Several key/tags of the '''[unit]''' and '''[attack]''' tags do not affect gameplay, but are available to control the way units and their attacks will be animated and heard.
  
All times (see ''begin'', ''end'', ''time'') are measured in milliseconds, or 1000ths of seconds. Unit movement is automatically animated based on these times; the attacking unit or missile begins in the     center of the hex at the lowest ''begin'' time, then slides continuously to the center of the defender's hex, which it reaches at time=0. If the attack is a melee attack, the unit will then slide continuously back onto its own hex until the highest ''end'' time. Note that in accelerated mode or under a lot of stress the game engine can skip some frames (sounds included), and very short frames (less than 10ms?) may get skipped even in normal circumstances.  
+
All times (see '''begin''', '''end''', '''time''') are measured in milliseconds, or 1000ths of seconds. Unit movement is automatically animated based on these times; the attacking unit or missile begins in the center of the hex at the lowest '''begin''' time, then slides continuously to the center of the defender's hex, which it reaches at time=0. If the attack is a melee attack, the unit will then slide continuously back onto its own hex until the highest '''end''' time. Note that in accelerated mode or under a lot of stress the game engine can skip some frames (sounds included), and very short frames (less than 10ms?) may get skipped even in normal circumstances.  
  
 
All unit animations use the same engine, so most tags and keys are common for all animations types.
 
All unit animations use the same engine, so most tags and keys are common for all animations types.
Line 11: Line 11:
 
=== [animation] blocks ===
 
=== [animation] blocks ===
  
All animations are enclosed in ''[animation]'' tags. The actual name of the tag changes depending on the type of animation (so for example healing animations are written inside ''[healing_anim]'' tags, death anims inside ''[death]'' tags, and so on).
+
All animations are enclosed in '''[animation]''' tags. The actual name of the tag changes depending on the type of animation (so for example healing animations are written inside '''[healing_anim]''' tags, death anims inside '''[death]''' tags, and so on).
  
Individual animation frames are described by ''[frame]'' tags.
+
Individual animation frames are described by '''[frame]''' tags.
  
* '''[animation]''' all animations are enclosed in ''[animation]'' tags. The actual name of the tag changes depending on the type of animation (so for example healing animations are written inside ''[healing_anim]'' tags, death anims inside ''[death]'' tags, and so on), but here we refer to all of them simply as ''[animation]'' tags, since they all work the same. Wherever you can put an ''[animation]'' tag, you can put multiple ones - you can use this to create variations on animations or to have some animations be used only in certain circumstances (like only on a certain terrain or only when delivering a killing blow in combat to name a few possibilities).
+
* '''[animation]''': all animations are enclosed in '''[animation]''' tags. The actual name of the tag changes depending on the type of animation (so for example healing animations are written inside '''[healing_anim]''' tags, death anims inside '''[death]''': tags, and so on), but here we refer to all of them simply as '''[animation]''' tags, since they all work the same. Wherever you can put an '''[animation]''': tag, you can put multiple ones - you can use this to create variations on animations or to have some animations be used only in certain circumstances (like only on a certain terrain or only when delivering a killing blow in combat to name a few possibilities).
** '''[frame]''' describes what an animation should display at a given time. Several frames cannot be displayed at the same time.
+
** '''[frame]''': describes what an animation should display at a given time. Only one frame can be displayed at a time.
*** ''begin'' the time at which this frame should start (in milliseconds).
+
*** '''begin''': the time at which this frame should start (in milliseconds).
*** ''end'' the time at which the animation should end.
+
*** '''end''': the time at which the animation should end.
*** ''duration'' {{DevFeature}} how long the frame should be displayed. Use instead of ''begin='' and ''end=''.
+
*** '''duration''': how long the frame should be displayed. Use instead of '''begin=''' and '''end='''.
*** ''image'' the image to display during the frame.
+
*** '''image''': the image to display during the frame.
*** ''sound'' the sound to play when the frame begins. Can be a comma-separated list of sounds, in which case one of them is chosen randomly every time.
+
*** '''sound''': the sound to play when the frame begins. Can be a comma-separated list of sounds, in which case one of them is chosen randomly every time.
*** ''halo'' the halo to display at the time.
+
*** '''halo''': the halo to display at the time.
*** ''halo_x'' the position the halo is displayed in pixel relative to the unit's center.
+
*** '''halo_x''': the position the halo is displayed in pixel relative to the unit's center.
*** ''halo_y'' the position the halo is displayed in pixel relative to the unit's center.
+
*** '''halo_y''': the position the halo is displayed in pixel relative to the unit's center.
*** ''alpha'' {{DevFeature}} transparency level to apply to the frame. This is a floating point progressive parameter ranging from 0.0 to 1.0.
+
*** '''alpha''': transparency level to apply to the frame. This is a floating point progressive parameter ranging from 0.0 to 1.0.
*** ''offset'' {{DevFeature}} the position of the image relative to the hex the unit is facing, 0.0 will display the unit in the center of the hex, 1.0 in the center of the faced hex, -1.0 at the center of the hex behind you. This is a progressive parameter.
+
*** '''offset''': the position of the image relative to the hex the unit is facing, 0.0 will display the unit in the center of the hex, 1.0 in the center of the faced hex, -1.0 at the center of the hex behind you. This is a progressive parameter.
*** ''blend_color'' {{DevFeature}} a comma separated list of numbers representing a color in RGB (0-255) this color will be mixed to the frame to give it a tint.
+
*** '''blend_color''': a comma separated list of numbers representing a color in RGB (0-255) this color will be mixed to the frame to give it a tint.
*** ''blend_ratio'' {{DevFeature}} this is a progressive parameter ranging from 0 to 1: 0 means no tint, 1 means target color only.
+
*** '''blend_ratio''': this is a progressive parameter ranging from 0 to 1: 0 means no tint, 1 means target color only.
*** ''text'' {{DevFeature}} if specified, floats a label with the given text above the unit (identical to the floating damage and healing numbers).
+
*** '''text''': if specified, floats a label with the given text above the unit (identical to the floating damage and healing numbers).
*** ''text_color'' {{DevFeature}} the colour of the above floating label.
+
*** '''text_color''': the color of the above floating label.
** '''[missile_frame]''' can only be used for ranged attacks; describes a frame of animation for the projectile. Most commonly only one ''[missile_frame]'' is used and the missile isn't actually animated. Accepts the same keys as ''[frame]'' and also the following:
+
** '''[missile_frame]''': can only be used for ranged attacks; describes a frame of animation for the projectile. Most commonly only one ''[missile_frame]'' is used and the missile isn't actually animated. Accepts the same keys as ''[frame]'' and also the following:
*** ''image_diagonal'' the image to display when the attack occurs diagonally (directions ne,se,sw,nw).
+
*** '''image_diagonal''': the image to display when the attack occurs diagonally (directions ne,se,sw,nw).
**'''[XXX_frame]''' {{DevFeature}} you can have as many "sub animations" within an animation by defining them in their own type of frame blocks. note that XXX should not start with an underscore ("_") this is reserver for internal use by the engine
+
**'''[XXX_frame]''': you can have as many "sub animations" within an animation by defining them in their own type of frame blocks. note that XXX should not start with an underscore ("_") this is reserver for internal use by the engine
*** ''image_diagonal'' the image to display when the animation occurs diagonally (directions ne,se,sw,nw).
+
*** '''image_diagonal''': the image to display when the animation occurs diagonally (directions ne,se,sw,nw).
  
 
==== Progressive parameters ====
 
==== Progressive parameters ====
  
You can make a value of a key smoothly slide from one starting value to another one during the duration of the ''[frame]''. To make a frame fade from normal to completely transparent, you could use:
+
You can make a value of a key smoothly slide from one starting value to another one during the duration of the '''[frame]'''. To make a frame fade from normal to completely transparent, you could use:
  
 
  alpha=1~0
 
  alpha=1~0
Line 50: Line 50:
 
  missile_offset=0~0.8
 
  missile_offset=0~0.8
  
 
+
When defining an animation for use in a specific situation, you have a variety of keys with which you can define when the animation is to be used. The filters go directly inside the '''[animation]''' tag. Different types of animations have slightly different set of filters available. See further below for a detailed explanation on how more complex filtering works.
When defining an animation for use in a specific situation, you have a variety of keys with which you can define when the animation is to be used. The filters go directly inside the ''[animation]'' tag. Different types of animations have slightly different set of filters available. See further below for a detailed explanation on how more complex filtering works.
 
  
 
'''Generic animation filters available for all animations'''
 
'''Generic animation filters available for all animations'''
* ''terrain'' a list of comma separated terrain letters, the animation will only be used on these terrains. (Note this code has some bugs the fix is '''''[[User:SkeletonCrew#Branch_terrain|(SVN terrain only)]]'''''). The terrain filter can also use the wildcard filter '''''[[User:SkeletonCrew#Branch_terrain|(SVN terrain only)]]''''' see [[FilterWML]].
+
* '''terrain''': a list of comma separated terrain letters, the animation will only be used on these terrains. See [[FilterWML]].
* ''direction'' a list of directions (n,ne,se,s,sw,nw), the animation will only be used when acting or moving in this direction (the attack direction for attack animations, moving direction for movement animations, direction of lead unit for leading animations, and so on).
+
* '''direction''': a list of directions (n,ne,se,s,sw,nw), the animation will only be used when acting or moving in this direction (the attack direction for attack animations, moving direction for movement animations, direction of lead unit for leading animations, and so on).
* ''frequency'' {{DevFeature}} this integer value allows to easily tweak the matching frequency of animations. The filter will fail n-1 times out of n, randomly. Note that unlike every other filter, matching this filter won't give an extra point.
+
* '''frequency''': this integer value allows to easily tweak the matching frequency of animations. The filter will fail n-1 times out of n, randomly. Note that unlike every other filter, matching this filter won't give an extra point.
* '''[unit_filter]''' {{DevFeature}} this will filter using a standard unit filter on the animated unit. Note that matching all criterias in the filter will only earn you one point for animation selection, but that you can have multiple ''[unit_filter]'' blocks in an animation.
+
* '''[unit_filter]''': this will filter using a standard unit filter on the animated unit. Note that matching all criterias in the filter will only earn you one point for animation selection, but that you can have multiple '''[unit_filter]''' blocks in an animation.
* '''[secondary_unit_filter]''' {{DevFeature}} this will filter using a standard unit filter on the unit in the hex faced. Note that matching all criterias in the filter will only earn you one point for animation selection, but that you can have multiple ''[secondary_unit_filter]'' blocks in an animation. Also note that if the faced hex is empty, the whole filter will fail
+
* '''[secondary_unit_filter]''': this will filter using a standard unit filter on the unit in the hex faced. Note that matching all criterias in the filter will only earn you one point for animation selection, but that you can have multiple '''[secondary_unit_filter]''' blocks in an animation. Also note that if the faced hex is empty, the whole filter will fail
* '''[neighbour_unit_filter]''' {{DevFeature}} this will filter using a standard unit filter on allunits in adjacent hexes. Note that matching all criterias in the filter will only earn you one point for animation selection, but that you can have multiple ''[neighbour_unit_filter]'' blocks in an animation. This filter will earn you one point for each matching neighbouring unit, and will fail if no unit matches the criteria (i.e no neighbour or no matching neighbour) .
+
* '''[neighbour_unit_filter]''': this will filter using a standard unit filter on allunits in adjacent hexes. Note that matching all criterias in the filter will only earn you one point for animation selection, but that you can have multiple '''[neighbour_unit_filter]''' blocks in an animation. This filter will earn you one point for each matching neighbouring unit, and will fail if no unit matches the criteria (i.e no neighbour or no matching neighbour) .
  
  
 
Progressive parameters can be set both in the '''[frame]''' or in the '''[animation]''' the general rule is that frame level specification overrides animation level specifications, which overrides engine provided defaults. The following parameters can be specified both at animation and at frame level
 
Progressive parameters can be set both in the '''[frame]''' or in the '''[animation]''' the general rule is that frame level specification overrides animation level specifications, which overrides engine provided defaults. The following parameters can be specified both at animation and at frame level
* ''alpha''
+
* '''alpha'''
* ''halo''
+
* '''halo'''
* ''halo_x''
+
* '''halo_x'''
* ''halo_y''
+
* '''halo_y'''
* ''offset''
+
* '''offset'''
* ''blend_color''
+
* '''blend_color'''
* ''blend_ratio''
+
* '''blend_ratio'''
  
 
Note that these can be set as animation-level parameters also for sub-animations (see [XXX_frame] above) by using keys XXX_offset, XXX_alpha, etc.
 
Note that these can be set as animation-level parameters also for sub-animations (see [XXX_frame] above) by using keys XXX_offset, XXX_alpha, etc.
Line 75: Line 74:
  
 
'''Fighting animation filters'''
 
'''Fighting animation filters'''
** ''hits'' filters attack animations based on whether the attack hits, misses or kills. Accepts a list of the following:
+
** '''hits''': filters attack animations based on whether the attack hits, misses or kills. Accepts a list of the following:
*** ''hit'' the attack hits, defender survives.
+
*** '''hit''': the attack hits, defender survives.
*** ''no'' or ''miss'' the attack misses.
+
*** '''no''' or '''miss''': the attack misses.
*** ''kill'' the attack hits, defender dies.
+
*** '''kill''': the attack hits, defender dies.
*** ''yes'' is an alias of ''hit,kill''.
+
*** '''yes''': is an alias of '''hit,kill'''.
** ''range'' a list of ranges that the attack must match for this animation to be used.
+
** '''range''': a list of ranges that the attack must match for this animation to be used.
** ''damage_type'' a list of damage types that the animation should be used with (damage type of the attack).
+
** '''damage_type''': a list of damage types that the animation should be used with (damage type of the attack).
** ''attack_special'' a list of special abilities the attack should have.
+
** '''attack_special''': a list of special abilities the attack should have.
** ''swing'' {{DevFeature}} a list of numbers representing the swing numbers this animation should match (numbered from 1).
+
** '''swing''': a list of numbers representing the swing numbers this animation should match (numbered from 1).
** ''damage'' a comma separated list of values of the damage the defender will take (note that damage is 0 if the attack misses).
+
** '''damage''': a comma separated list of values of the damage the defender will take (note that damage is 0 if the attack misses).
** '''[attack_filter]''' {{DevFeature}} a standard attack filter to match on the attacker's attack. See  [[FilterWML]].
+
** '''[attack_filter]''': a standard attack filter to match on the attacker's attack. See  [[FilterWML]].
** '''[secondary_attack_filter]''' {{DevFeature}} a standard attack filter to match on the defender's attack. See [[FilterWML]]. Also note that if the defender doesn't have any weapon to retaliate with, this filter will always fail.
+
** '''[secondary_attack_filter]''': a standard attack filter to match on the defender's attack. See [[FilterWML]]. Also note that if the defender doesn't have any weapon to retaliate with, this filter will always fail.
 
 
==== Attack animation: ''[animation]'' within an ''[attack]'' block ====
 
 
 
This animation is played when a unit attempts a blow on another unit. The attacking unit is always facing the defending unit.
 
 
 
Also note that unlike all other animations, this one is in the ''[attack]'' block, not directly in the ''[unit]'' block. Please see the special case of the ''[missile_frame]'' below.
 
 
 
{{DevFeature}} : this is deprecated, see below
 
  
==== Attack animation: ''[attack_anim]'' {{DevFeature}} ====
+
==== Attack animation: ''[attack_anim]'' ====
  
 
This animation is played when a unit attempts a blow on another unit. The attacking unit is always facing the defending unit.
 
This animation is played when a unit attempts a blow on another unit. The attacking unit is always facing the defending unit.
Line 118: Line 109:
 
This animation is used when a unit is standing and doing nothing.
 
This animation is used when a unit is standing and doing nothing.
  
==== Idle animation: ''[idle_anim]'' {{DevFeature}} ====
+
==== Idle animation: ''[idle_anim]'' ====
  
 
This animation is called randomly every now and then when the unit is idle.
 
This animation is called randomly every now and then when the unit is idle.
Line 129: Line 120:
  
 
This animation is used when a unit has a healing ability and is using it on another unit. The healing unit is always facing the unit it heals.
 
This animation is used when a unit has a healing ability and is using it on another unit. The healing unit is always facing the unit it heals.
* ''damage'' a comma separated list of values: the damage healed.
+
* '''damage''': a comma separated list of values: the damage healed.
  
 
==== Teleport animation: ''[teleport_anim]'' ====
 
==== Teleport animation: ''[teleport_anim]'' ====
Line 139: Line 130:
 
This animation is used when the unit kills another unit, during the other unit's death animation. It is called after the fight is finished and the hits criteria is always set to kill.
 
This animation is used when the unit kills another unit, during the other unit's death animation. It is called after the fight is finished and the hits criteria is always set to kill.
  
==== Poison animation: ''[poison_anim]'' {{DevFeature}} ====
+
==== Poison animation: ''[poison_anim]'' ====
  
 
This animation is used when the unit suffers poison damage (at the beginning of turn).
 
This animation is used when the unit suffers poison damage (at the beginning of turn).
* ''damage'' a comma separated list of values: the damage suffered.
+
* ''damage'': a comma separated list of values: the damage suffered.
  
==== Healed animation: ''[healed_anim]'' {{DevFeature}} ====
+
==== Healed animation: ''[healed_anim]'' ====
  
 
This animation is used when the unit is healed (by a healer or a village).
 
This animation is used when the unit is healed (by a healer or a village).
* ''healing'' a comma separated list of values: the HP healed.
+
* ''healing'': a comma separated list of values: the HP healed.
  
==== Recruit animation: ''[recruit_anim]'' {{DevFeature}} ====
+
==== Recruit animation: ''[recruit_anim]'' ====
  
 
This animation is used when a unit is recruited (or created via the plague special ability).
 
This animation is used when a unit is recruited (or created via the plague special ability).
  
==== Level in animation: ''[levelin_anim]'' {{DevFeature}} ====
+
==== Level-in animation: ''[levelin_anim]'' ====
  
 
This animation is used when a unit has leveled. The new unit is displayed, and this animation is played immediately.
 
This animation is used when a unit has leveled. The new unit is displayed, and this animation is played immediately.
  
==== Level out animation: ''[levelout_anim]'' {{DevFeature}} ====
+
==== Level-out animation: ''[levelout_anim]'' ====
  
 
This animation is used when a unit has leveled. The old unit is still displayed, and this animation is played just before changing it to the new unit.
 
This animation is used when a unit has leveled. The old unit is still displayed, and this animation is played just before changing it to the new unit.
Line 164: Line 155:
  
 
This animation defines a custom animation that can be called in WML events (via the ''[animate_unit]'' tag), to make a unit display arbitrary animations at arbitrary times.
 
This animation defines a custom animation that can be called in WML events (via the ''[animate_unit]'' tag), to make a unit display arbitrary animations at arbitrary times.
* ''flag'' this identifies the animation, and will be used to choose the correct animation to play.
+
* '''flag''': this identifies the animation, and will be used to choose the correct animation to play.
  
 
== How animations are chosen ==
 
== How animations are chosen ==
Line 195: Line 186:
 
== How animations are synchronized ==
 
== How animations are synchronized ==
  
Some events require multiple units playing different animations simultaneously. Typically a fight involves a unit playing it's defense animation while the opponent plays it's attack animation (and a third might play it's leading animation, too).
+
Some events require multiple units playing different animations simultaneously. Typically a fight involves a unit playing its defense animation while the opponent plays it's attack animation (and a third might play its leading animation, too).
  
 
In that case, it is very important that these animations (which can have different lengths) be synchronized. Fight animations are synchronized around the point of impact, so they all reach time 0 when the attack lands (or misses).
 
In that case, it is very important that these animations (which can have different lengths) be synchronized. Fight animations are synchronized around the point of impact, so they all reach time 0 when the attack lands (or misses).
  
In {{DevFeature}}, where one should use ''duration='' to time ''[frame]''s instead of the ''begin='' and ''end='' keys, animation blocks can specify a ''start_time='' key. This is a virtual time at which the animation should be launched. Suppose the attack animation has ''start_time=-150'' and the defense animation has ''start_time=-100'': for 50ms, the attack animation will play alone, then the defense animation will start, they will both reach their virtual 0 at the same time (which is the time of impact) and then continue. If no ''start_time'' is available, it is defaulted to zero.
+
When you use '''duration=''' to time '''[frame]'''s instead of the '''begin=''' and '''end=''' keys (which is recommended), animation blocks can specify a '''start_time=''' key. This is a virtual time at which the animation should be launched. Suppose the attack animation has '''start_time=-150''' and the defense animation has '''start_time=-100''': for 50ms, the attack animation will play alone, then the defense animation will start, they will both reach their virtual 0 at the same time (which is the time of impact) and then continue. If no '''start_time''' is available, it is defaulted to zero.
  
  
 
== ''[if]'' and ''[else]'' ==
 
== ''[if]'' and ''[else]'' ==
  
If you need to do very slight variations in an animation (like a different sound depending on whether the unit hits or misses it's attack), the ''[if]'' and ''[else]'' tags are useful. Using these in an animation is equivalent to having multiple animations, one with the ''[if]'' block and one with each of the ''[else]'' blocks. Any filtering flags in these blocks will replace the toplevel filters. You can have multiple ''[if]'' blocks in an animation, but you can't nest an ''[if]'' inside another. These should be written directly inside the ''[animation]'' block. The following example would make the ''[frame]'' inside the ''[if]'' be played when the attack misses, and the ''[frame]'' inside the ''[else]'' be played when the attack hits (producing a different sound):
+
If you need to do very slight variations in an animation (like a different sound depending on whether the unit hits or misses its attack), the '''[if]''' and '''[else]''' tags are useful. Using these in an animation is equivalent to having multiple animations, one with the '''[if]''' block and one with each of the ''[else]'' blocks. Any filtering flags in these blocks will replace the toplevel filters. You can have multiple '''[if]''' blocks in an animation, but you can't nest an '''[if]''' inside another. These should be written directly inside the '''[animation]''' block. The following example would make the '''[frame]''' inside the '''[if]''' be played when the attack misses, and the '''[frame]''' inside the '''[else]''' be played when the attack hits (producing a different sound):
  
 
     [if]
 
     [if]

Revision as of 12:55, 19 February 2008

[edit]WML Tags

A:

abilities, about, achievement, achievement_group, add_ai_behavior, advanced_preference, advancefrom, advancement, advances, affect_adjacent, ai, allied_with, allow_end_turn, allow_extra_recruit, allow_recruit, allow_undo, and, animate, animate_unit, animation, aspect, attack (replay, weapon), attack_anim, attacks (special, stats), avoid;

B:

base_unit, background_layer, berserk, binary_path, break, brush;

C:

campaign, cancel_action, candidate_action, capture_village, case, chance_to_hit, change_theme, chat, checkbox, choice, choose, clear_global_variable, clear_menu_item, clear_variable, color_adjust, color_palette, color_range, command (action, replay), continue, credits_group, criteria;

D:

damage, death, deaths, default, defend, defends, defense, delay, deprecated_message, destination, difficulty, disable, disallow_end_turn, disallow_extra_recruit, disallow_recruit, do, do_command, drains, draw_weapon_anim;

E:

editor_group, editor_music, editor_times, effect, else (action, animation), elseif, endlevel, end_turn (action, replay), enemy_of, engine, entry (credits, options), era, event, experimental_filter_ability, experimental_filter_ability_active, experimental_filter_specials, extra_anim;

F:

facet, facing, fake_unit, false, feedback, female, filter (concept, event), filter_adjacent, filter_adjacent_location, filter_attack, filter_attacker, filter_base_value, filter_condition, filter_defender, filter_enemy, filter_location, filter_opponent, filter_own, filter_owner, filter_radius, filter_recall, filter_second, filter_second_attack, filter_self, filter_side, filter_student, filter_vision, filter_weapon, filter_wml, find_path, fire_event, firststrike, floating_text, found_item, for, foreach, frame;

G:

game_config, get_global_variable, goal, gold, gold_carryover;

H:

harm_unit, has_ally, has_attack, has_unit, has_achievement, have_location, have_unit, heal_on_hit, heal_unit, healed_anim, healing_anim, heals, hide_help, hide_unit, hides;

I:

idle_anim, if (action, animation, intro), illuminates, image (intro, terrain), init_side, insert_tag, inspect, item, item_group;

J:

jamming_costs, join;

K:

kill, killed;

L:

label, language, leader, leader_goal, leadership, leading_anim, levelin_anim, levelout_anim, lift_fog, limit, literal, load_resource, locale, lock_view, lua;

M:

male, menu_item, message, micro_ai, missile_frame, modification, modifications, modify_ai, modify_side, modify_turns, modify_unit, modify_unit_type, move, move_unit, move_unit_fake, move_units_fake, movement_anim, movement costs, movetype, multiplayer, multiplayer_side, music;

N:

not, note;

O:

object, objective, objectives, on_undo, open_help, option, options, or;

P:

part, petrifies, petrify, place_shroud, plague, poison, post_movement_anim, pre_movement_anim, primary_attack, primary_unit, print, progress_achievement, put_to_recall_list;

R:

race, random_placement, recall (action, replay), recalls, recruit, recruit_anim, recruiting_anim, recruits, redraw, regenerate, remove_event, remove_item, remove_object, remove_shroud, remove_sound_source, remove_time_area, remove_trait, remove_unit_overlay, repeat, replace_map, replace_schedule, replay, replay_start, reset_fog, resistance (ability, unit), resistance_defaults, resource, return, role, rule;

S:

save, scenario, screen_fade, scroll, scroll_to, scroll_to_unit, secondary_attack, secondary_unit, section, select_unit, sequence, set_achievement, set_extra_recruit, set_global_variable, set_menu_item, set_recruit, set_specials, set_variable, set_variables, sheath_weapon_anim, show_if (message, objective, set_menu_item), show_objectives, side, skirmisher, slider, slow, snapshot, sound, sound_source, source (replay, teleport), special_note, specials, split, stage, standing_anim, statistics, status, store_gold, store_items, store_locations, store_map_dimensions, store_reachable_locations, store_relative_direction, store_side, store_starting_location, store_time_of_day, store_turns, store_unit, store_unit_defense, store_unit_defense_on, store_unit_type, store_unit_type_ids, store_villages, story, swarm, sub_achievement, switch, sync_variable;

T:

target, team, teleport (ability, action), teleport_anim, terrain, terrain_defaults, terrain_graphics, terrain_mask, terrain_type, test, test_condition, test_do_attack_by_id, text_input, textdomain, theme, then, tile, time, time_area, topic, toplevel, trait, transform_unit, traveler, true, tunnel;

U:

unhide_unit, unit, unit_overlay, unit_type, unit_worth, units, unlock_view, unpetrify, unstore_unit, unsynced;

V:

value, variable, variables, variant, variation, victory_anim, village, vision_costs, volume;

W:

while, wml_message, wml_schema;

Z:

zoom;

Animation and sound

Several key/tags of the [unit] and [attack] tags do not affect gameplay, but are available to control the way units and their attacks will be animated and heard.

All times (see begin, end, time) are measured in milliseconds, or 1000ths of seconds. Unit movement is automatically animated based on these times; the attacking unit or missile begins in the center of the hex at the lowest begin time, then slides continuously to the center of the defender's hex, which it reaches at time=0. If the attack is a melee attack, the unit will then slide continuously back onto its own hex until the highest end time. Note that in accelerated mode or under a lot of stress the game engine can skip some frames (sounds included), and very short frames (less than 10ms?) may get skipped even in normal circumstances.

All unit animations use the same engine, so most tags and keys are common for all animations types.

[animation] blocks

All animations are enclosed in [animation] tags. The actual name of the tag changes depending on the type of animation (so for example healing animations are written inside [healing_anim] tags, death anims inside [death] tags, and so on).

Individual animation frames are described by [frame] tags.

  • [animation]: all animations are enclosed in [animation] tags. The actual name of the tag changes depending on the type of animation (so for example healing animations are written inside [healing_anim] tags, death anims inside [death]: tags, and so on), but here we refer to all of them simply as [animation] tags, since they all work the same. Wherever you can put an [animation]: tag, you can put multiple ones - you can use this to create variations on animations or to have some animations be used only in certain circumstances (like only on a certain terrain or only when delivering a killing blow in combat to name a few possibilities).
    • [frame]: describes what an animation should display at a given time. Only one frame can be displayed at a time.
      • begin: the time at which this frame should start (in milliseconds).
      • end: the time at which the animation should end.
      • duration: how long the frame should be displayed. Use instead of begin= and end=.
      • image: the image to display during the frame.
      • sound: the sound to play when the frame begins. Can be a comma-separated list of sounds, in which case one of them is chosen randomly every time.
      • halo: the halo to display at the time.
      • halo_x: the position the halo is displayed in pixel relative to the unit's center.
      • halo_y: the position the halo is displayed in pixel relative to the unit's center.
      • alpha: transparency level to apply to the frame. This is a floating point progressive parameter ranging from 0.0 to 1.0.
      • offset: the position of the image relative to the hex the unit is facing, 0.0 will display the unit in the center of the hex, 1.0 in the center of the faced hex, -1.0 at the center of the hex behind you. This is a progressive parameter.
      • blend_color: a comma separated list of numbers representing a color in RGB (0-255) this color will be mixed to the frame to give it a tint.
      • blend_ratio: this is a progressive parameter ranging from 0 to 1: 0 means no tint, 1 means target color only.
      • text: if specified, floats a label with the given text above the unit (identical to the floating damage and healing numbers).
      • text_color: the color of the above floating label.
    • [missile_frame]: can only be used for ranged attacks; describes a frame of animation for the projectile. Most commonly only one [missile_frame] is used and the missile isn't actually animated. Accepts the same keys as [frame] and also the following:
      • image_diagonal: the image to display when the attack occurs diagonally (directions ne,se,sw,nw).
    • [XXX_frame]: you can have as many "sub animations" within an animation by defining them in their own type of frame blocks. note that XXX should not start with an underscore ("_") this is reserver for internal use by the engine
      • image_diagonal: the image to display when the animation occurs diagonally (directions ne,se,sw,nw).

Progressive parameters

You can make a value of a key smoothly slide from one starting value to another one during the duration of the [frame]. To make a frame fade from normal to completely transparent, you could use:

alpha=1~0

To make a frame, which is 900ms long, slide to transparent for 300ms, stay transparent for another 300ms and finally fade back to normal for 300ms, use:

alpha=1~0:300,0:300,0~1:300

if you want to define this parameter for other sub animation, use the prefix of that animation. For instance, the default sliding of missile animations can be specified with

missile_offset=0~0.8

When defining an animation for use in a specific situation, you have a variety of keys with which you can define when the animation is to be used. The filters go directly inside the [animation] tag. Different types of animations have slightly different set of filters available. See further below for a detailed explanation on how more complex filtering works.

Generic animation filters available for all animations

  • terrain: a list of comma separated terrain letters, the animation will only be used on these terrains. See FilterWML.
  • direction: a list of directions (n,ne,se,s,sw,nw), the animation will only be used when acting or moving in this direction (the attack direction for attack animations, moving direction for movement animations, direction of lead unit for leading animations, and so on).
  • frequency: this integer value allows to easily tweak the matching frequency of animations. The filter will fail n-1 times out of n, randomly. Note that unlike every other filter, matching this filter won't give an extra point.
  • [unit_filter]: this will filter using a standard unit filter on the animated unit. Note that matching all criterias in the filter will only earn you one point for animation selection, but that you can have multiple [unit_filter] blocks in an animation.
  • [secondary_unit_filter]: this will filter using a standard unit filter on the unit in the hex faced. Note that matching all criterias in the filter will only earn you one point for animation selection, but that you can have multiple [secondary_unit_filter] blocks in an animation. Also note that if the faced hex is empty, the whole filter will fail
  • [neighbour_unit_filter]: this will filter using a standard unit filter on allunits in adjacent hexes. Note that matching all criterias in the filter will only earn you one point for animation selection, but that you can have multiple [neighbour_unit_filter] blocks in an animation. This filter will earn you one point for each matching neighbouring unit, and will fail if no unit matches the criteria (i.e no neighbour or no matching neighbour) .


Progressive parameters can be set both in the [frame] or in the [animation] the general rule is that frame level specification overrides animation level specifications, which overrides engine provided defaults. The following parameters can be specified both at animation and at frame level

  • alpha
  • halo
  • halo_x
  • halo_y
  • offset
  • blend_color
  • blend_ratio

Note that these can be set as animation-level parameters also for sub-animations (see [XXX_frame] above) by using keys XXX_offset, XXX_alpha, etc.


Fighting animation filters

    • hits: filters attack animations based on whether the attack hits, misses or kills. Accepts a list of the following:
      • hit: the attack hits, defender survives.
      • no or miss: the attack misses.
      • kill: the attack hits, defender dies.
      • yes: is an alias of hit,kill.
    • range: a list of ranges that the attack must match for this animation to be used.
    • damage_type: a list of damage types that the animation should be used with (damage type of the attack).
    • attack_special: a list of special abilities the attack should have.
    • swing: a list of numbers representing the swing numbers this animation should match (numbered from 1).
    • damage: a comma separated list of values of the damage the defender will take (note that damage is 0 if the attack misses).
    • [attack_filter]: a standard attack filter to match on the attacker's attack. See FilterWML.
    • [secondary_attack_filter]: a standard attack filter to match on the defender's attack. See FilterWML. Also note that if the defender doesn't have any weapon to retaliate with, this filter will always fail.

Attack animation: [attack_anim]

This animation is played when a unit attempts a blow on another unit. The attacking unit is always facing the defending unit.

This animation can contain some [missile_frame] blocks, see below...

Defensive animation: [defend]

This animation is used when facing a blow in a fight. The defending unit is always facing the attacking unit.

Death animation: [death]

This animation is used when the unit dies, before it is removed from display. It is called after the fight is finished and the hits criteria is always set to kill.

Movement animation: [movement_anim]

This animation is used when a unit is moving. The moving unit is always facing the hex it's moving into. The animation will be truncated if the unit reaches its destination before the end of the movement. The animation will also be ended if the unit enters a hex where the current animation has a negative score, but not if its still valid (but not the best score).

Standing animation: [standing_anim]

This animation is used when a unit is standing and doing nothing.

Idle animation: [idle_anim]

This animation is called randomly every now and then when the unit is idle.

Leading animation: [leading_anim]

This animation is used when a unit is using it's leadership ability on another unit. The leading unit is always facing the unit it leads.

Healing animation: [healing_anim]

This animation is used when a unit has a healing ability and is using it on another unit. The healing unit is always facing the unit it heals.

  • damage: a comma separated list of values: the damage healed.

Teleport animation: [teleport_anim]

This animation is used when a unit teleports by using the teleport ability (not when the unit is moved by using the [teleport] tag). The part of the animation before time 0 is displayed at the starting point, and the rest displayed when arriving at the destination.

Victory animation: [victory_anim]

This animation is used when the unit kills another unit, during the other unit's death animation. It is called after the fight is finished and the hits criteria is always set to kill.

Poison animation: [poison_anim]

This animation is used when the unit suffers poison damage (at the beginning of turn).

  • damage: a comma separated list of values: the damage suffered.

Healed animation: [healed_anim]

This animation is used when the unit is healed (by a healer or a village).

  • healing: a comma separated list of values: the HP healed.

Recruit animation: [recruit_anim]

This animation is used when a unit is recruited (or created via the plague special ability).

Level-in animation: [levelin_anim]

This animation is used when a unit has leveled. The new unit is displayed, and this animation is played immediately.

Level-out animation: [levelout_anim]

This animation is used when a unit has leveled. The old unit is still displayed, and this animation is played just before changing it to the new unit.

Custom animations: [extra_anim]

This animation defines a custom animation that can be called in WML events (via the [animate_unit] tag), to make a unit display arbitrary animations at arbitrary times.

  • flag: this identifies the animation, and will be used to choose the correct animation to play.

How animations are chosen

Wherever you can put an animation block, you can put multiple ones. So an interesting question is which one of them will the engine choose when the animation should be displayed? Simply put, the engine always chooses the one that matches the given filtering best. If several match equally well, one of them is picked randomly every time. Below is a more detailed and technical explanation of the choosing process.

The animation engine always uses the same rules to choose an animation. I will take the example from movement animations. Movement animations can take two filters (via special flags in the animation block) to filter on movement direction and on the terrain the unit is currently on. So, the engine takes all movement animations and assigns them scores with the following algorithm:

the animation starts with a score of 0 for each criteria,

  • if filter is not there, the score is unchanged
  • if filter is not matched the animation is given a score of -1 and the algorithm ends (disqualified)
  • if filter is matched, the score is increased by one

After that, the engine takes all top score animations and chooses a random one.

so, if we have a unit with

  1. an animation for water terrain
  2. an animation for SE on grassland
  3. an animation with no criteria
  4. an animation for N,NE,NW,S,SW,SE
  5. an animatio for NW
  • 3. will never be taken, because 4. will always trump it
  • on water going NW, it can be 1. 4. 5.
  • on water, any direction but NW, it will be 1. or 4.
  • on SE grassland it will be 2.
  • on other grasslands, it will be 4. (4. or 5. if NW)


How animations are synchronized

Some events require multiple units playing different animations simultaneously. Typically a fight involves a unit playing its defense animation while the opponent plays it's attack animation (and a third might play its leading animation, too).

In that case, it is very important that these animations (which can have different lengths) be synchronized. Fight animations are synchronized around the point of impact, so they all reach time 0 when the attack lands (or misses).

When you use duration= to time [frame]s instead of the begin= and end= keys (which is recommended), animation blocks can specify a start_time= key. This is a virtual time at which the animation should be launched. Suppose the attack animation has start_time=-150 and the defense animation has start_time=-100: for 50ms, the attack animation will play alone, then the defense animation will start, they will both reach their virtual 0 at the same time (which is the time of impact) and then continue. If no start_time is available, it is defaulted to zero.


[if] and [else]

If you need to do very slight variations in an animation (like a different sound depending on whether the unit hits or misses its attack), the [if] and [else] tags are useful. Using these in an animation is equivalent to having multiple animations, one with the [if] block and one with each of the [else] blocks. Any filtering flags in these blocks will replace the toplevel filters. You can have multiple [if] blocks in an animation, but you can't nest an [if] inside another. These should be written directly inside the [animation] block. The following example would make the [frame] inside the [if] be played when the attack misses, and the [frame] inside the [else] be played when the attack hits (producing a different sound):

   [if]
       hits=no
       [frame]
           begin=-100
           end=100
           image="units/dwarves/lord-attack.png"
           sound={SOUND_LIST:MISS}
       [/frame]
   [/if]
   [else]
       hits=yes
       [frame]
           begin=-100
           end=100
           image="units/dwarves/lord-attack.png"
           sound=axe.ogg
       [/frame]
   [/else]


See Also