#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 ATTRIBUTE ON_EASY ON_NORMAL ON_HARD # Macro to define a 'quantity' differently based on difficulty levels. #ifdef EASY {ATTRIBUTE}={ON_EASY} #endif #ifdef NORMAL {ATTRIBUTE}={ON_NORMAL} #endif #ifdef HARD {ATTRIBUTE}={ON_HARD} #endif #enddef #define TURNS ON_EASY ON_NORMAL ON_HARD # Macro to define number of turns for different difficulty levels. {QUANTITY turns {ON_EASY} {ON_NORMAL} {ON_HARD}} #enddef #define GOLD ON_EASY ON_NORMAL ON_HARD # Macro which will let you say {GOLD x y z} to set # starting gold depending on easy/medium/hard - x/y/z {QUANTITY gold {ON_EASY} {ON_NORMAL} {ON_HARD}} #enddef #define INCOME ON_EASY ON_NORMAL ON_HARD # 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 {ON_EASY} {ON_NORMAL} {ON_HARD}} #enddef #define ATTACK_DEPTH ON_EASY ON_NORMAL ON_HARD # Macro to define AI attack depth for different difficulty levels # (set it to 1-6) {QUANTITY attack_depth {ON_EASY} {ON_NORMAL} {ON_HARD}} #enddef #define NO_SCOUTS # Macro to make an AI team not recruit scouts. villages_per_scout=0 #enddef #define RANDOM RANGE # Macro to quickly pick a random value (in the $random variable, to avoid # cluttering up savegames with such temporary variables). [set_variable] name=random random={RANGE} [/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 ARG # Macro to do mathematical operations on variables. [set_variable] name={VAR} {OP}={ARG} [/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 DEBUG_MSG MSG # Emit a debug message. Meant to be overridden with no-op definition # of the same name for production use. [message] speaker=narrator message={MSG} 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 STORE_UNIT_VAR FILTER VAR TO_VAR # Stores an attribute of a unit to the given variable. # # Example where this is used to flip all orcs to whatever side James is on: #! {STORE_UNIT_VAR description=James side side_of_James} #! {MODIFY_UNIT race=orc side $side_of_James} [store_unit] [filter] {FILTER} [/filter] kill=no variable=STORE_UNIT_VAR_store [/store_unit] {VARIABLE_OP {TO_VAR} format $STORE_UNIT_VAR_store.{VAR}} {CLEAR_VARIABLE STORE_UNIT_VAR_store} #enddef #define GENERIC_UNIT SIDE TYPE X Y # Creates a generic unit of TYPE belonging to SIDE at X,Y, which has a # random name and traits (just like a recruited unit). [unit] side={SIDE} type={TYPE} x={X} y={Y} generate_description=yes random_traits=yes upkeep=full [/unit] #enddef #define CREATE_UNIT SIDE TYPE X Y UNIT_ID OTHER # Creates a unit of TYPE belonging to SIDE at X,Y. UNIT_ID can be used # when filtering on it. For example, let's create a wose for player 1 # at 4,7 # #! {CREATE_UNIT 1 "Wose" 4 7 () ()} # # As a second example, let's make it a female wose which can recruit and # is name "Woselina": # #! {CREATE_UNIT 1 "Wose" 4 7 "Woselina" ( # canrecruit=1 # )} [unit] side={SIDE} type={TYPE} x={X} y={Y} description={UNIT_ID} user_description=" " upkeep=full animate=yes {OTHER} [/unit] #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 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. [event] name=side turn first_time_only=no [if] [variable] name=side_number numerical_equals={SIDE} [/variable] [then] [store_unit] [filter] side={SIDE} canrecruit=1 [/filter] kill=no variable=stored_side_{SIDE}_leader [/store_unit] {MODIFY_UNIT ( side={SIDE} canrecruit=1 ) canrecruit 0} [/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] #all the types of villages terrain=Ha^Vhha, Hh^Vhh, Dd^Vda, Mm^Vhh, Uu^Vu, Aa^Vea, Gs^Vht, Uu^Vud, Gg^Ve, Dd^Vdt, Gg^Vh, Aa^Vha, Ww^Vm, Ss^Vhs, Ss^Vm [and] x,y=$temp_starting_location.x,$temp_starting_location.y radius={RADIUS} [/and] variable=temp_starting_locs [/store_locations] {FOREACH temp_starting_locs i} {VARIABLE_OP temp_x_var to_variable temp_starting_locs[$i].x} {VARIABLE_OP temp_y_var to_variable temp_starting_locs[$i].y} [capture_village] side={SIDE} x,y=$temp_x_var,$temp_y_var [/capture_village] {NEXT i} {CLEAR_VARIABLE temp_x_var} {CLEAR_VARIABLE temp_y_var} {CLEAR_VARIABLE temp_starting_location} {CLEAR_VARIABLE temp_starting_locs} {CLEAR_VARIABLE i} [/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 UNIT TYPE DESCRIPTION UDESCRIPTION SIDE X Y # Create a unit with the Loyal trait. # # Example: #! {UNIT (Elvish Fighter) (Myname) ( _ "Myname") 1 1 1} # [unit] type={TYPE} description={DESCRIPTION} user_description={UDESCRIPTION} side={SIDE} x={X} y={Y} [modifications] {TRAIT_LOYAL} [/modifications] [/unit] #enddef #define LOYAL_UNIT SIDE TYPE X Y DESCRIPTION USER_DESCRIPTION # Creates a unit with the Loyal trait. Should make the too vaguely named # UNIT macro above obsolete. # # Example: #! {LOYAL_UNIT 1 19 16 (Elvish Fighter) (Myname) ( _ "Myname")} # [unit] type={TYPE} description={DESCRIPTION} user_description={USER_DESCRIPTION} side={SIDE} x={X} y={Y} [modifications] {TRAIT_LOYAL} [/modifications] [/unit] #enddef #define UNDEAD_UNIT TYPE SIDE X Y # Create a unit with the Undead and Loyal traits. [unit] type={TYPE} side={SIDE} x={X} y={Y} [modifications] {TRAIT_UNDEAD} {TRAIT_LOYAL} [/modifications] [/unit] #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 CONTENTS # 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} {CONTENTS} {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