mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-03 02:03:16 +00:00
577 lines
15 KiB
INI
577 lines
15 KiB
INI
#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 MP_GENERIC_UNIT SIDE TYPE X Y
|
|
# Creates a generic unit of TYPE belonging to SIDE at X,Y, which has a
|
|
# random name no traits.
|
|
# This can be removed and GENERIC_UNIT be used instead once random traits
|
|
# work in multiplayer.
|
|
[unit]
|
|
side={SIDE}
|
|
type={TYPE}
|
|
x={X}
|
|
y={Y}
|
|
generate_description=yes
|
|
random_traits=no
|
|
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.
|
|
#
|
|
# 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=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
|