Difference between revisions of "WML Utilities"
From The Battle for Wesnoth Wiki
(→Determining opposite coordinates: bugfix s/ modulo for *0.5 then *2 which doesnt work in 1.6 due to floating point variables) |
(Added search macro) |
||
Line 168: | Line 168: | ||
{CLEAR_VARIABLE result_y} | {CLEAR_VARIABLE result_y} | ||
{CLEAR_VARIABLE x_odd} | {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 | #enddef | ||
Revision as of 06:19, 29 September 2009
Contents
Filter by Terrain
# Check whethers or not the terrain in the given coordinates is of the given # type or types. Filtering by terrain isn't possible directly. # # You can use it for example like this: # # [event] # name=moveto # first_time_only=no # # {IF_TERRAIN $x1 $y1 Gg,Gs^Fp,Mm ( # [then] # {DEBUG_MSG "Stepped on grassland, forest or mountains!"} # [/then] # )} # [/event]
#define IF_TERRAIN X Y TERRAIN CONTENTS [store_locations] x={X} y={Y} terrain={TERRAIN} variable=IF_TERRAIN_temp [/store_locations]
[if] [variable] name=IF_TERRAIN_temp.length not_equals=0 [/variable]
{CONTENTS} [/if]
{CLEAR_VARIABLE IF_TERRAIN_temp} #enddef
Iterate
# You can iterate through a range of numbers with this macro. The CONTENTS # are repeated with every iteration, and you can use the VAR variable to # insert the number of the current step into each iteration. Note that # when using this, you must iterate from a smaller number to the bigger # number, because the increment is always 1. # # Example that spawns a row of skeletons into the coordinates (4,5), # (5,5), (6,5), (7,5), (8,5) and (9,5): # # {ITERATE 4 9 i ( # [unit] # type=Skeleton # x=$i # y=5 # [/unit] # )}
#define ITERATE FROM TO VAR CONTENTS {VARIABLE {VAR} {FROM}}
[while] [variable] name={VAR} less_than_equal_to={TO} [/variable]
[do] {CONTENTS}
{VARIABLE_OP {VAR} add 1} [/do] [/while] #enddef
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