Difference between revisions of "AnimationWML"

From The Battle for Wesnoth Wiki
m (A note about skipping frames)
(First edit to update the page to 1.2 - will fix rest soon)
Line 1: Line 1:
 
{{WML Tags}}
 
{{WML Tags}}
 +
 +
'''The page is getting a bigger overhaul, so things are a bit messy right now.'''
 +
 
== Animation and sound ==
 
== Animation and sound ==
  
Several key/tags of the [unit] and [attack] tags do not affect gameplay,
+
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.
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. Several frames cannot be displayed at the same time.
 +
*** ''begin'' the time at which this frame should start (in milliseconds).
 +
*** ''end'' the time at which the animation should 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.
 +
** '''[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).
 +
 
 +
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_type'' a list of terrain letters, the animation will only be used on these terrains.
 +
** ''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).
 +
 
 +
'''Attack animation filters'''
 +
** ''hits'' filters attack animations based on whether the attack hits, misses or kills. Accepts a list of the following:
 +
*** ''yes'' or ''hit'' the attack hits, defender survives.
 +
*** ''no'' or ''miss'' the attack misses.
 +
*** ''kill'' the attack hits, defender dies.
 +
** ''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.
 +
 
 +
== 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?
 +
 
 +
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 assign it a score 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
 +
# an animation for water terrain
 +
# an animation for SE on grassland
 +
# an animation with no criteria
 +
# an animation for N,NE,NW,S,SW,SE
 +
# 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)
 +
== the ''[if]'' and ''[else]'' statements ==
 +
sometime, you will want to do very slight variations in an anim (like a different sound when a unit is hit or not).
 +
 
 +
to do that, the ''[if]'' and ''[else]'' tags are used.
 +
 
 +
and ''[if]'' block is usually followed by one or more ''[else]'' blocks
 +
having no ''[else]'' block is equivalent to having an empty ''[else]'' block after the ''[if]''
 +
 
 +
having this in an animation is ewuivalent to having multiple animations, one with the ''[if]'' block and one with each of the ''[else]'' block
 +
 
 +
these tags should be directly in the [animation] block.
 +
any flag in these blocks will replace the toplevel flags
 +
 
 +
note that you can have multiple ''[if]'' blocks in an anim, they will expand independantly, however, you can't nest these blocks
 +
 
 +
 
  
All images assume that units are facing right;
 
when units are facing left the images will be reversed.
 
If a unit is attacking north or south then an "orthogonal" image
 
may be displayed for the unit's missile (see [missile_frame]).
 
The input file is displayed when the unit is attacking northwards,
 
and flipped horizontally when the unit attacks southwards.
 
  
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 short-range,
 
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 25ms) may get skipped even in normal circumstances.
 
  
 
* '''[frame]''' In WML, animations are made using the '''[frame]''' tag. It describes one frame of an animation. The following keys are recognized for '''[frame]''':
 
* '''[frame]''' In WML, animations are made using the '''[frame]''' tag. It describes one frame of an animation. The following keys are recognized for '''[frame]''':

Revision as of 21:56, 3 September 2006

[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;

The page is getting a bigger overhaul, so things are a bit messy right now.

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. Several frames cannot be displayed at the same time.
      • begin the time at which this frame should start (in milliseconds).
      • end the time at which the animation should 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.
    • [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).

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_type a list of terrain letters, the animation will only be used on these terrains.
    • 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).

Attack animation filters

    • hits filters attack animations based on whether the attack hits, misses or kills. Accepts a list of the following:
      • yes or hit the attack hits, defender survives.
      • no or miss the attack misses.
      • kill the attack hits, defender dies.
    • 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.

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?

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 assign it a score 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)

the [if] and [else] statements

sometime, you will want to do very slight variations in an anim (like a different sound when a unit is hit or not).

to do that, the [if] and [else] tags are used.

and [if] block is usually followed by one or more [else] blocks having no [else] block is equivalent to having an empty [else] block after the [if]

having this in an animation is ewuivalent to having multiple animations, one with the [if] block and one with each of the [else] block

these tags should be directly in the [animation] block. any flag in these blocks will replace the toplevel flags

note that you can have multiple [if] blocks in an anim, they will expand independantly, however, you can't nest these blocks



  • [frame] In WML, animations are made using the [frame] tag. It describes one frame of an animation. The following keys are recognized for [frame]:
    • begin when to start displaying this frame
    • end when to stop displaying this frame
    • image the image to display during this frame to represent the unit
    • halo comma separated list of halo images to be displayed around the unit. The duration of images can be given with colons after the image name - else these images will be given equal amounts of time, based on the time between begin and end. It is recommended that you allow for at least 50 time units per image; i.e. end - beginning > 50 * number of halos. halo is generally used only for long-range attack animations (both [frame] and [missile_frame]). Example:
      halo = "img1:10,img2:20,img3:10"
    • halo_x,halo_y pixel offset between the center of the halo images and the center of the unit.
    • sound Template:DevFeature the sound to play (at the begining) when this frame is displayed: if a comma-separated list, one is chosen randomly. If a list is used, then the same sound won't be picked from it two times in a row. The list can contain the same sound several times, which can be used for example to avoid an alternating pattern in a list of just two sounds, by changing sound=sound1.ogg,sound2.ogg to sound=sound1.ogg,sound2.ogg,sound1.ogg,sound2.ogg.

The following display key/tags are recognized for [unit]:

  • image the unit image displayed on the main map when the unit is resting, and on the status table when the unit is selected. Also the default for all other unit images.
  • profile the image displayed when the unit is talking. See [message], InterfaceActionsWML.
  • image_moving the image displayed while the unit is moving, this is deprecated in 1.1.x, see [movement_animation] below.
  • image_long the image displayed while the unit is using a long-range (ranged) attack (can be overloaded; see [frame], [attack]).
  • image_short the image displayed while the unit is using a short-range (melee) attack (can be overloaded; see [frame], [attack]).
  • image_leading,image_healing the images displayed for this unit while using the 'leadership', 'heals', or 'cures' ability, if present. See also AbilitiesWML.
  • image_halo_healing a halo (see above) used together with image_healing
  • [teleport_anim] describes an animation for when this unit teleports.
    • [frame] see [frame] above. The frames before time 0 are displayed at the original location; the ones after are displayed at the new location.
  • image_defensive default for image_defensive_long and image_defensive_short this is deprecated in 1.1.x see [defend].
  • image_defensive_long default image when the unit is defending against a long-range attack. This is deprecated in 1.1.x see [defend].
  • image_defensive_short default image when the unit is defending against a short-range attack. This is depecated in 1.1.x see [defend].
  • [defend] describes an animation for when this unit defends. Multiple [defend]s tags can be used.
    • range if this key is present, the attack must be at this range in order for the animation to trigger. Values 'short', 'long'. Template:DevFeature: this is a comma separated list of ranges to filter the defensive animation, values must be the same than the one in the range flag of the corresponding attack (melee and ranged for standard wesnoth)
    • hits if this key is present, the attack must either hit('yes') or miss('no') in order for this animation to trigger.
    • [frame] defense animation. See [frame] above.
  • get_hit_sound the sound played (at time=0) when this unit is hit. Template:DevFeature If a comma-separated list, one is chosen at random.
  • die_sound the sound played (at time=0) when the unit dies. Template:DevFeature If a comma-separated list, one is chosen at random.
  • [death] describes an animation for when this unit is killed. Times before 0 are not allowed for this animation; the first frame's begin time will be displayed immediately following the unit's defense animation, regardless of whether it is before or after 0.
    • [frame] death animation. See [frame] above.
  • [extra_anim] Template:DevFeature describes a unit animation that will be displayed on a [animate_unit] wml action
    • flag this tag will be used to choose the animation to play. If a unit has more than one animaiton with a given tag, a random one will be choosen
    • [frame] the animation itself, see [frame] above
  • [movement_anim] describe an animation to use when the unit is moving. multiple animations are allowed
    • terrain a comma separated list of letters, this animation will only be used on these terrains
    • direction a comma separated list of directions, the animations will only be used when moving in these directions

The following display tags are recognized for [attack] (deprecated in 1.1.x, use the [animation] tag described in unitWML which has the same syntax):

  • hits Template:DevFeature if this key is present, the attack must either hit('yes') or miss('no') in order for this animation to trigger.
  • direction (only in an [animation] tag ) a comma separated list of directions, the animations will only be used when moving in these directions
  • [frame] unit's attack animation. For melee attacks (range=short), this animation is moved toward the enemy; otherwise it is stationary. See [frame] above for syntax.
  • [missile_frame] missile's animation during the attack. Only valid for ranged attacks (range=long).
    • begin,end,halo,halo_x,halo_y same as in [frame] above.
    • image the image to display when the unit is attacking orthogonally.
    • image_diagonal the image to display if the unit is attacking diagonally.
  • [sound] describes a sound to play during the attack (deprecated in 1.1.x, please use the sound= line in frames instead)
    • sound the sound to play if the attack hits. Template:DevFeature If a comma-separated list, one is chosen at random.
    • sound_miss the sound to play if the attack misses. Template:DevFeature If a comma-separated list, one is chosen at random.
    • time when to start playing the sound

See Also