WML Utilities

From The Battle for Wesnoth Wiki
Revision as of 20:58, 31 May 2010 by Zookeeper (talk | contribs) (Removed an obsolete and a rather useless macro)

Adding unit overlays with a filter instead of (x,y)

# UNIT_OVERLAY adds an overlay to a unit, taking in a standard filter
#
# Example that gives all spearmen a book:
# {UNIT_OVERLAY type=Spearman items/book1.png}

#define UNIT_OVERLAY FILTER IMG
    [store_unit]
        [filter]
            {FILTER}
        [/filter]
        variable=UNIT_OVERLAY_store
        kill=no
    [/store_unit]
    {FOREACH UNIT_OVERLAY_store UNIT_OVERLAY_i}
	{VARIABLE_OP UNIT_OVERLAY_tempx format $UNIT_OVERLAY_store[$UNIT_OVERLAY_i].x}
	{VARIABLE_OP UNIT_OVERLAY_tempy format $UNIT_OVERLAY_store[$UNIT_OVERLAY_i].y}
        [unit_overlay]
            x=$UNIT_OVERLAY_tempx
            y=$UNIT_OVERLAY_tempy
		image={IMG}
        [/unit_overlay]
    {NEXT UNIT_OVERLAY_i}
    {CLEAR_VARIABLE UNIT_OVERLAY_store}
#enddef

Determining opposite coordinates

# Using this, you can determine the coordinates on the "opposite side" of a
# central hex, relative to another hex adjacent to it. What this really means
# is illustrated below:
#       __            __            __
#    __/  \__      __/2 \__      __/  \__
#   /  \__/1 \    /  \__/  \    /2 \__/  \    C: central point
#   \__/C \__/    \__/C \__/    \__/C \__/    1: the hex to "mirror"
#   /2 \__/  \    /  \__/  \    /  \__/1 \    2: the result
#   \__/  \__/    \__/1 \__/    \__/  \__/
#      \__/          \__/          \__/
#
# The coordinates of the central point are given in {CENTER_X} and {CENTER_Y},
# and the coordinates of hex 1 in {X} and {Y}. The coordinates of hex 2 are
# then stored in {VAR}, which will have member variables x and y.
#
# Note that this uses the IF macro given earlier on this page.
#define OPPOSITE_SIDE CENTER_X CENTER_Y X Y VAR {VARIABLE x_odd {X}}
{VARIABLE_OP x_odd modulo 2}
{VARIABLE c_x {CENTER_X}} {VARIABLE c_y {CENTER_Y}} {VARIABLE s_x {X}} {VARIABLE s_y {Y}}
{VARIABLE result_x {CENTER_X}} {VARIABLE result_y {CENTER_Y}}
{IF_VAR s_x greater_than $c_x ( [then] {VARIABLE_OP result_x add -1} [/then] )}
{IF_VAR s_x less_than $c_x ( [then] {VARIABLE_OP result_x add 1} [/then] )}
{IF_VAR s_x equals $c_x ( [then] {IF_VAR s_y less_than $c_y ( [then] {VARIABLE_OP result_y add 1} [/then] )}
{IF_VAR s_y greater_than $c_y ( [then] {VARIABLE_OP result_y add -1} [/then] )} [/then] )}
{IF_VAR x_odd equals 1 ( [then] {IF_VAR s_y equals $c_y ( [then] {VARIABLE_OP result_y add 1} [/then] )} [/then]
[else] {IF_VAR s_y equals $c_y ( [then] {VARIABLE_OP result_y add -1} [/then] )} [/else] )} {VARIABLE {VAR}.x $result_x} {VARIABLE {VAR}.y $result_y}
{CLEAR_VARIABLE c_x} {CLEAR_VARIABLE c_y} {CLEAR_VARIABLE s_x} {CLEAR_VARIABLE s_y} {CLEAR_VARIABLE result_x} {CLEAR_VARIABLE result_y} {CLEAR_VARIABLE x_odd} #enddef

Find nearest hex(es)

#define FIND_NEARBY FILTER X Y LIMIT
    # Does a search for a nearby location that matches the given filter.
    # Basically just looks for such a location with increasing radius until it
    # finds at least one. This is sadly inefficient, but implementing BFS in
    # WML is... difficult. Once LIMIT is reached, the entire map is searched.
    # This macro creates the 'nearby_locations' and 'nearby_distance'
    # variables, which can be used to access a list of locations found and the
    # distance to those locations, respectively. They should eventually be
    # cleared, which can be accomplished using the CLEANUP_SEARCH macro.
    [clear_variable]
        name=nearby_locations
    [/clear_variable]
    [set_variable]
        name=nearby_distance
        value=0
    [/set_variable]
    [while]
        [not]
            [variable]
                name=nearby_locations.length
                greater_than=0
            [/variable]
        [/not]
        [and]
            [variable]
                name=nearby_distance
                less_than={LIMIT}
            [/variable]
        [/and]
        [do]
            {DEBUG "Searching depth $nearby_distance around ({X}, {Y})..."}
            [store_locations]
                variable=nearby_locations
                {FILTER}
                [and]
                    x,y={X},{Y}
                    radius=$nearby_distance
                [/and]
            [/store_locations]
            {DEBUG "...found $nearby_locations.length locations."}
            [set_variable]
                name=nearby_distance
                add=1
            [/set_variable]
        [/do]
    [/while]
    [if]
        [variable]
            name=nearby_locations.length
            equals=0
        [/variable]
        [then]
            [store_locations]
                variable=nearby_locations
                {FILTER}
            [/store_locations]
        [/then]
    [/if]
#enddef

#define CLEANUP_SEARCH
    # Clears variables involved in searching (the FIND_NEARBY macro). Put this
    # in your name=victory,defeat tag to clean up if you use FIND_NEARBY within
    # a scenario.
    [clear_variable]
        name=nearby_locations, nearby_distance
    [/clear_variable]
#enddef

See Also