#textdomain wesnoth
# This file contains general utility macros for WML authors.
#
# Later macros in this file are built using earlier ones, which
# is why they live hear rather than being broken out into topic-specific files.

# ! in comments is used in generating HTML documentation, ignore it otherwise. 
#define QUANTITY NAME EASY_VALUE NORMAL_VALUE HARD_VALUE
    # Macro to define a 'quantity' differently based on difficulty levels.
#ifdef EASY
    {NAME}={EASY_VALUE}
#endif
#ifdef NORMAL
    {NAME}={NORMAL_VALUE}
#endif
#ifdef HARD
    {NAME}={HARD_VALUE}
#endif
#enddef

#define TURNS EASY_AMOUNT NORMAL_AMOUNT HARD_AMOUNT
    # Macro to define number of turns for different difficulty levels.
    {QUANTITY turns {EASY_AMOUNT} {NORMAL_AMOUNT} {HARD_AMOUNT}}
#enddef

#define GOLD EASY_AMOUNT NORMAL_AMOUNT HARD_AMOUNT
    # Macro which will let you say {GOLD x y z} to set
    # starting gold depending on easy/medium/hard - x/y/z
    {QUANTITY gold {EASY_AMOUNT} {NORMAL_AMOUNT} {HARD_AMOUNT}}
#enddef

#define INCOME EASY_AMOUNT NORMAL_AMOUNT HARD_AMOUNT
    # Macro which will let you say {GOLD x y z} to set
    # per-turn income depending on easy/medium/hard - x/y/z
    {QUANTITY income {EASY_AMOUNT} {NORMAL_AMOUNT} {HARD_AMOUNT}}
#enddef

#define ATTACK_DEPTH EASY_VALUE NORMAL_VALUE HARD_VALUE
    # Macro to define AI attack depth for different difficulty levels
    # (set it to 1-6)
    {QUANTITY attack_depth {EASY_VALUE} {NORMAL_VALUE} {HARD_VALUE}}
#enddef

#define NO_SCOUTS
    # Macro to make an AI team not recruit scouts.
    villages_per_scout=0
#enddef

#define RANDOM THING
    # Macro to quickly pick a random value (in the $random variable, to avoid
    # cluttering up savegames with such temporary variables).
    [set_variable]
        name=random
        rand={THING}
    [/set_variable]
#enddef

#define VARIABLE VAR VALUE
    # Macro to initialize a variable.  Strictly a syntatic shortcut.
    [set_variable]
        name={VAR}
        value={VALUE}
    [/set_variable]
#enddef

#define VARIABLE_OP VAR OP_NAME VALUE
    # Macro to do mathematical operations on variables.
    [set_variable]
        name={VAR}
        {OP_NAME}={VALUE}
    [/set_variable]
#enddef

#define CLEAR_VARIABLE VAR
    # Macro to clear a variable previously set.
    [clear_variable]
        name={VAR}
    [/clear_variable]
#enddef

# wmlindent: start ignoring
#define FOREACH ARRAY VAR
# Macro to begin a WML clause that iterates over an array.
{VARIABLE {VAR} 0}
[while]
    [variable]
    name={VAR}
    less_than=${ARRAY}.length
    [/variable]
    [do]
#enddef

#define NEXT VAR
# Macro to end a WML clause that iterates over an array.
    [set_variable]
    name={VAR}
    add=1
    [/set_variable]
    [/do]
[/while]
{CLEAR_VARIABLE {VAR}}
#enddef
# wmlindent: stop ignoring

#define REPEAT NUMBER BODY_WML
    {VARIABLE REPEAT_i 0}

    [while]
        [variable]
            name=REPEAT_i
            less_than={NUMBER}
        [/variable]

        [do]
            {BODY_WML}

            {VARIABLE_OP REPEAT_i add 1}
        [/do]
    [/while]

    {CLEAR_VARIABLE REPEAT_i}
#enddef

#define DEBUG_MSG MESSAGE
    # Emit a debug message.  Meant to be overridden with no-op definition
    # of the same name for production use.
    [message]
        speaker=narrator
        message={MESSAGE}
        image=wesnoth-icon.png
    [/message]
#enddef

#define MODIFY_UNIT FILTER VAR VALUE
    # Alters a unit variable (such as unit.x, unit.type,
    # unit.side), handling all the storing and unstoring.
    #
    # Example that flips all spearmen to side 2:
    #! {MODIFY_UNIT type=Spearman side 2}
    [store_unit]
        [filter]
            {FILTER}
        [/filter]

        variable=MODIFY_UNIT_store
        kill=yes
    [/store_unit]

    {FOREACH MODIFY_UNIT_store MODIFY_UNIT_i}
    [set_variable]
        name=MODIFY_UNIT_store[$MODIFY_UNIT_i].{VAR}
        value={VALUE}
    [/set_variable]

    [unstore_unit]
        variable=MODIFY_UNIT_store[$MODIFY_UNIT_i]
        find_vacant=no
    [/unstore_unit]
    {NEXT MODIFY_UNIT_i}

    {CLEAR_VARIABLE MODIFY_UNIT_store}
#enddef

#define MOVE_UNIT FILTER TO_X TO_Y
    # Moves a unit from its current location to the given location along a
    # relatively straight line displaying the movement just like
    # [move_unit_fake] does.
    #
    # Note that setting the destination on an existing unit does not kill either
    # one, but causes the unit to move to the nearest vacant hex instead.
    [store_unit]
        [filter]
            {FILTER}
        [/filter]

        variable=MOVE_UNIT_temp
        kill=no
    [/store_unit]

    [scroll_to]
        x=$MOVE_UNIT_temp.x
        y=$MOVE_UNIT_temp.y
    [/scroll_to]

    {VARIABLE_OP MOVE_UNIT_path_coords_x format ("$MOVE_UNIT_temp.x|,{TO_X}")}
    {VARIABLE_OP MOVE_UNIT_path_coords_y format ("$MOVE_UNIT_temp.y|,{TO_Y}")}

    [if]
        [variable]
            name=MOVE_UNIT_temp.x
            less_than={TO_X}
        [/variable]

        [then]
            {VARIABLE MOVE_UNIT_temp.facing se}
        [/then]

        [else]
            [if]
                [variable]
                    name=MOVE_UNIT_temp.x
                    greater_than={TO_X}
                [/variable]

                [then]
                    {VARIABLE MOVE_UNIT_temp.facing sw}
                [/then]
            [/if]
        [/else]
    [/if]

    {VARIABLE MOVE_UNIT_temp.x {TO_X}}
    {VARIABLE MOVE_UNIT_temp.y {TO_Y}}

    [kill]
        {FILTER}

        animate=no
        fire_event=no
    [/kill]

    [move_unit_fake]
        type=$MOVE_UNIT_temp.type
        gender=$MOVE_UNIT_temp.gender
        variation=$MOVE_UNIT_temp.variation
        side=$MOVE_UNIT_temp.side
        x=$MOVE_UNIT_path_coords_x
        y=$MOVE_UNIT_path_coords_y
    [/move_unit_fake]

    [unstore_unit]
        variable=MOVE_UNIT_temp
        find_vacant=yes
    [/unstore_unit]

    [redraw][/redraw]
    {CLEAR_VARIABLE MOVE_UNIT_temp}
    {CLEAR_VARIABLE MOVE_UNIT_path_coords_x}
    {CLEAR_VARIABLE MOVE_UNIT_path_coords_y}
#enddef

#define NO_SCROLL_TO_AI_LEADER SIDE
    # Prevents the view from scrolling to the leader of a specific AI
    # side at the beginning of its turn. Useful if that side doesn't
    # really do anything and the scrolling distance would be long
    # enough to be annoying every turn (for example on a big
    # map). Does not work on human-controlled sides.
    #
    # Warning: in networked MP this will cause the game to think the
    # leader of this side has been defeated when changing turns and
    # thus might lead to victory/defeat being declared prematurely.
    [event]
        name=side turn
        first_time_only=no

        [if]
            [variable]
                name=side_number
                numerical_equals={SIDE}
            [/variable]

            [then]
                [store_unit]
                    [filter]
                        side={SIDE}
                        canrecruit=yes
                    [/filter]

                    kill=no
                    variable=stored_side_{SIDE}_leader
                [/store_unit]

                {MODIFY_UNIT (
                side={SIDE}
                canrecruit=yes
                ) canrecruit no}
            [/then]
        [/if]
    [/event]

    [event]
        name=ai turn
        first_time_only=no

        [if]
            [variable]
                name=side_number
                numerical_equals={SIDE}
            [/variable]

            [then]
                [unstore_unit]
                    variable=stored_side_{SIDE}_leader
                    find_vacant=no
                [/unstore_unit]

                {CLEAR_VARIABLE stored_side_{SIDE}_leader}
            [/then]
        [/if]
    [/event]
#enddef

#define FULL_HEAL FILTER
    # This heals the specified unit(s) to full health. Does not work on units on
    # a recall list.
    [store_unit]
        [filter]
            {FILTER}
        [/filter]

        kill=no
        variable=FULL_HEAL_temp
    [/store_unit]

    {FOREACH FULL_HEAL_temp FULL_HEAL_i}
    [object]
        silent=yes

        [filter]
            x,y=$FULL_HEAL_temp[$FULL_HEAL_i].x,$FULL_HEAL_temp[$FULL_HEAL_i].y
        [/filter]

        [effect]
            apply_to=hitpoints
            heal_full=yes
        [/effect]
    [/object]
    {NEXT FULL_HEAL_i}

    {CLEAR_VARIABLE FULL_HEAL_temp}
    {CLEAR_VARIABLE FULL_HEAL_i}
#enddef

#define PUT_TO_RECALL_LIST FILTER
    # This places a given unit back to the recall list of the side it is on.
    # Note however, that the unit is not healed to full health, so when
    # recalled (even if not until the next scenario) the unit may have less
    # than his maximum hp left.
    #
    # An example that returns all units stepping on (20,38) back to the recall
    # list:
    #
    #! [event]
    #!     name=moveto
    #!
    #!     [filter]
    #!         x,y=20,38
    #!     [/filter]
    #!
    #!     {PUT_TO_RECALL_LIST x,y=20,38}
    #! [/event]
    [store_unit]
        [filter]
            {FILTER}
        [/filter]

        variable=PUT_TO_RECALL_LIST_temp
        kill=yes
    [/store_unit]

    {FOREACH PUT_TO_RECALL_LIST_temp i}
    {VARIABLE PUT_TO_RECALL_LIST_temp[$i].x "recall"}
    {VARIABLE PUT_TO_RECALL_LIST_temp[$i].y "recall"}

    [unstore_unit]
        variable=PUT_TO_RECALL_LIST_temp[$i]
        find_vacant=no
    [/unstore_unit]
    {NEXT i}
#enddef

#define STARTING_VILLAGES SIDE RADIUS
    # Macro to make a side start a scenario with villages
    [event]
        name=prestart

        [store_starting_location]
            side={SIDE}
            variable=temp_starting_location
        [/store_starting_location]

        [store_locations]
            terrain=*^V*
            [and]
                x,y=$temp_starting_location.x,$temp_starting_location.y
                radius={RADIUS}
            [/and]
            variable=temp_starting_villages
        [/store_locations]

        {FOREACH temp_starting_villages i}
        [capture_village]
            side={SIDE}
            x,y=$temp_starting_villages[$i].x,$temp_starting_villages[$i].y
        [/capture_village]
        {NEXT i}

        {CLEAR_VARIABLE temp_starting_villages}
    [/event]
#enddef

#define STARTING_VILLAGES_AREA SIDE X Y RADIUS
    # Make a side start with ownership of villages in a given area.
    [event]
        name=prestart

        [store_locations]
            terrain=*^V*
            [and]
                x,y={X},{Y}
                radius={RADIUS}
            [/and]
            variable=temp_starting_villages_area
        [/store_locations]

        {FOREACH temp_starting_villages_area i}
        [capture_village]
            side={SIDE}
            x,y=$temp_starting_villages_area[$i].x,$temp_starting_villages_area[$i].y
        [/capture_village]
        {NEXT i}

        {CLEAR_VARIABLE temp_starting_villages_area}
    [/event]
#enddef

#define TRANSFER_VILLAGE_OWNERSHIP FROM_SIDE TO_SIDE
    # Transfers ownership of all villages of one side to another side. Useful
    # when you're for example moving all units of some side to another, and want
    # to transfer the village ownership as well.
    [store_villages]
        owner_side={FROM_SIDE}
        variable=TRANSFER_VILLAGE_OWNERSHIP_villages
    [/store_villages]

    {FOREACH TRANSFER_VILLAGE_OWNERSHIP_villages TRANSFER_VILLAGE_OWNERSHIP_i}
        [capture_village]
            x,y=$TRANSFER_VILLAGE_OWNERSHIP_villages[$TRANSFER_VILLAGE_OWNERSHIP_i].x,$TRANSFER_VILLAGE_OWNERSHIP_villages[$TRANSFER_VILLAGE_OWNERSHIP_i].y
            side={TO_SIDE}
        [/capture_village]
    {NEXT TRANSFER_VILLAGE_OWNERSHIP_i}

    {CLEAR_VARIABLE TRANSFER_VILLAGE_OWNERSHIP_villages}
    {CLEAR_VARIABLE TRANSFER_VILLAGE_OWNERSHIP_i}
#enddef

# FIXME: Documentation for these is needed.

#define MENU_IMG_TXT IMG TXT
    "&"+{IMG}+"="+{TXT}#enddef

#define MENU_IMG_TXT2 IMG TXT1 TXT2
    "&"+{IMG}+"="+{TXT1}+"="+{TXT2}#enddef

#define TIME_ACTIONS CONTENT_WML
    # Measure (in milliseconds) the time arbitrary event WML takes to
    # execute.  Afterwards, the time the enclosed WML took to execute
    # is found in the variable $timed_actions_ms.
    #
    # Example:
    #! [event]
    #!     name=start
    #!
    #!     {TIME_ACTIONS (
    #!         {MODIFY_UNIT race=orc user_description ( _ "Azir")}
    #!     )}
    #!
    #!     {DEBUG_MSG "Renaming all orcs to Azir took $timed_actions_ms|ms."}
    #! [/event]
    {VARIABLE_OP TIME_ACTIONS_time_begin time stamp}

    {CONTENT_WML}

    {VARIABLE_OP TIME_ACTIONS_time_end time stamp}

    {VARIABLE timed_actions_ms $TIME_ACTIONS_time_end}
    {VARIABLE_OP timed_actions_ms add "-$TIME_ACTIONS_time_begin"}

    {CLEAR_VARIABLE TIME_ACTIONS_time_begin}
    {CLEAR_VARIABLE TIME_ACTIONS_time_end}
#enddef
