mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-02 03:57:17 +00:00
624 lines
12 KiB
INI
624 lines
12 KiB
INI
# This file contains general utility macros for WML authors.
|
|
#
|
|
# Also see
|
|
|
|
#### TABLE OF CONTENTS ####
|
|
|
|
# variable operations
|
|
|
|
# RANDOM
|
|
# VARIABLE
|
|
# VARIABLE_OP
|
|
# CLEAR_VARIABLE
|
|
# FOREACH
|
|
# NEXT
|
|
# IF_TERRAIN
|
|
# DEBUG_MSG
|
|
|
|
# scenario/campaign setup
|
|
|
|
# DEFAULT_MUSIC_PLAYLIST
|
|
# SCENARIO_MUSIC
|
|
# STARTING_VILLAGES
|
|
# DOT
|
|
# CROSS
|
|
# MENU_IMG_TXT
|
|
# MENU_IMG_TXT2
|
|
|
|
# side setup
|
|
|
|
# TURNS
|
|
# GOLD
|
|
# INCOME
|
|
# ATTACK_DEPTH
|
|
# NO_SCOUTS
|
|
|
|
# in-scenario actions
|
|
|
|
# PLACE_IMAGE
|
|
# TREMOR
|
|
# IS_HERO
|
|
# UNIT
|
|
# UNDEAD_UNIT
|
|
# CREATE_UNIT
|
|
# MOVE_UNIT
|
|
# MODIFY_UNIT
|
|
# STORE_UNIT_VAR
|
|
# PUT_TO_RECALL_LIST
|
|
|
|
# utilities not intended for general use
|
|
|
|
# QUANTITY
|
|
# MAGENTA_IS_THE_TEAM_COLOR
|
|
# COLOR_HEAL
|
|
# COLOR_HARM
|
|
# COLOR_WHITE
|
|
|
|
#### END OF TABLE OF CONTENTS ####
|
|
|
|
#macro to define a 'quantity' differently based on difficulty levels
|
|
#define QUANTITY ATTRIBUTE ON_EASY ON_NORMAL ON_HARD
|
|
#ifdef EASY
|
|
{ATTRIBUTE}={ON_EASY}
|
|
#endif
|
|
|
|
#ifdef NORMAL
|
|
{ATTRIBUTE}={ON_NORMAL}
|
|
#endif
|
|
|
|
#ifdef HARD
|
|
{ATTRIBUTE}={ON_HARD}
|
|
#endif
|
|
#enddef
|
|
|
|
#macro to define number of turns for different difficulty levels
|
|
#define TURNS ON_EASY ON_NORMAL ON_HARD
|
|
{QUANTITY turns {ON_EASY} {ON_NORMAL} {ON_HARD}}
|
|
#enddef
|
|
|
|
#macro which will let you go {GOLD x y z} to set
|
|
#the gold depending on easy/medium/hard - x/y/z
|
|
|
|
#define GOLD ON_EASY ON_NORMAL ON_HARD
|
|
{QUANTITY gold {ON_EASY} {ON_NORMAL} {ON_HARD}}
|
|
#enddef
|
|
|
|
#define INCOME ON_EASY ON_NORMAL ON_HARD
|
|
{QUANTITY income {ON_EASY} {ON_NORMAL} {ON_HARD}}
|
|
#enddef
|
|
|
|
#macro to define AI attack depth for different difficulty levels (set it to 1-6)
|
|
#define ATTACK_DEPTH ON_EASY ON_NORMAL ON_HARD
|
|
{QUANTITY attack_depth {ON_EASY} {ON_NORMAL} {ON_HARD}}
|
|
#enddef
|
|
|
|
#macro to make an AI team not recruit scouts
|
|
#define NO_SCOUTS
|
|
villages_per_scout=0
|
|
#enddef
|
|
|
|
#macro to add a hero icon to the unit
|
|
#define IS_HERO
|
|
overlays="misc/hero-icon.png"
|
|
#enddef
|
|
|
|
#define DOT X Y
|
|
[image]
|
|
x,y={X},{Y}
|
|
file=misc/dot.png
|
|
delay=500
|
|
[/image]
|
|
#enddef
|
|
|
|
#define CROSS X Y
|
|
[image]
|
|
x,y={X},{Y}
|
|
file=misc/cross.png
|
|
delay=500
|
|
[/image]
|
|
#enddef
|
|
|
|
|
|
#macro to quickly pick a random value (in the $random variable, to avoid
|
|
#cluterring up savegames with such temporary variables)
|
|
|
|
#define RANDOM RANGE
|
|
[set_variable]
|
|
name=random
|
|
random={RANGE}
|
|
[/set_variable]
|
|
#enddef
|
|
|
|
#macro to initialize a variable
|
|
#define VARIABLE VAR VALUE
|
|
[set_variable]
|
|
name={VAR}
|
|
value={VALUE}
|
|
[/set_variable]
|
|
#enddef
|
|
|
|
#macro to do mathematical operations on variables
|
|
#define VARIABLE_OP VAR OP ARG
|
|
[set_variable]
|
|
name={VAR}
|
|
{OP}={ARG}
|
|
[/set_variable]
|
|
#enddef
|
|
|
|
#define CLEAR_VARIABLE VAR
|
|
[clear_variable]
|
|
name={VAR}
|
|
[/clear_variable]
|
|
#enddef
|
|
|
|
#macro to iterate over an array
|
|
#define FOREACH ARRAY VAR
|
|
{VARIABLE {VAR} 0}
|
|
[while]
|
|
[variable]
|
|
name={VAR}
|
|
less_than=${ARRAY}.length
|
|
[/variable]
|
|
[do]
|
|
#enddef
|
|
|
|
#define NEXT VAR
|
|
[set_variable]
|
|
name={VAR}
|
|
add=1
|
|
[/set_variable]
|
|
[/do]
|
|
[/while]
|
|
{CLEAR_VARIABLE {VAR}}
|
|
#enddef
|
|
|
|
#define DEBUG_MSG MSG
|
|
[message]
|
|
speaker=narrator
|
|
message={MSG}
|
|
[/message]
|
|
#enddef
|
|
|
|
|
|
|
|
# MODIFY_UNIT 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}
|
|
|
|
#define MODIFY_UNIT FILTER VAR VALUE
|
|
[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
|
|
|
|
|
|
# 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}
|
|
|
|
#define STORE_UNIT_VAR FILTER VAR TO_VAR
|
|
[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
|
|
|
|
|
|
# This is a way to check whether or not the terrain in the given coordinates
|
|
# is of the given type or types. Might be useful, since 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 gfm (
|
|
# [then]
|
|
# {DEBUG_MSG "Stepped on grassland, forest or mountains!"}
|
|
# [/then]
|
|
# )}
|
|
# [/event]
|
|
|
|
#define IF_TERRAIN X Y TYPES CONTENTS
|
|
[store_locations]
|
|
x={X}
|
|
y={Y}
|
|
terrain={TYPES}
|
|
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
|
|
|
|
|
|
# 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
|
|
# )}
|
|
|
|
#define CREATE_UNIT SIDE TYPE X Y UNIT_ID OTHER
|
|
[unit]
|
|
side={SIDE}
|
|
type={TYPE}
|
|
x={X}
|
|
y={Y}
|
|
description={UNIT_ID}
|
|
|
|
upkeep=full
|
|
animate=yes
|
|
{OTHER}
|
|
[/unit]
|
|
#enddef
|
|
# 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.
|
|
|
|
#define MOVE_UNIT FILTER TO_X TO_Y
|
|
[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]
|
|
|
|
[hide_unit]
|
|
x=$MOVE_UNIT_temp.x
|
|
y=$MOVE_UNIT_temp.y
|
|
[/hide_unit]
|
|
|
|
{VARIABLE_OP x_coords format ("$MOVE_UNIT_temp.x|,{TO_X}")}
|
|
{VARIABLE_OP y_coords format ("$MOVE_UNIT_temp.y|,{TO_Y}")}
|
|
|
|
[move_unit_fake]
|
|
type=$MOVE_UNIT_temp.type
|
|
x=$x_coords
|
|
y=$y_coords
|
|
[/move_unit_fake]
|
|
|
|
[teleport]
|
|
[filter]
|
|
{FILTER}
|
|
[/filter]
|
|
|
|
x,y={TO_X},{TO_Y}
|
|
[/teleport]
|
|
|
|
[unhide_unit][/unhide_unit]
|
|
|
|
[redraw][/redraw]
|
|
#enddef
|
|
|
|
|
|
# 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]
|
|
|
|
#define PUT_TO_RECALL_LIST FILTER
|
|
[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
|
|
|
|
|
|
#macro to make a side start a scenario with villages
|
|
|
|
#define STARTING_VILLAGES SIDE RADIUS
|
|
[event]
|
|
name=prestart
|
|
[store_starting_location]
|
|
side={SIDE}
|
|
variable=temp_starting_location
|
|
[/store_starting_location]
|
|
[store_locations]
|
|
x,y=$temp_starting_location.x,$temp_starting_location.y
|
|
radius={RADIUS}
|
|
variable=temp_starting_locs
|
|
|
|
#all the types of villages
|
|
terrain=Vhha, Vhh, Vda, Vhm, Vu, Vea, Vht, Vud, Veg, Vdt, Vhg, Vha, Vwm, Vs
|
|
[/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 MENU_IMG_TXT IMG TXT
|
|
"&"+{IMG}+"="+{TXT}#enddef
|
|
|
|
#define MENU_IMG_TXT2 IMG TXT1 TXT2
|
|
"&"+{IMG}+"="+{TXT1}+"="+{TXT2}#enddef
|
|
|
|
#
|
|
#USAGE {UNIT (Elvish Fighter) (Myname) ( _ "Myname") 1 1 1}
|
|
#
|
|
|
|
#define UNIT TYPE DESCRIPTION UDESCRIPTION SIDE X Y
|
|
[unit]
|
|
type={TYPE}
|
|
description={DESCRIPTION}
|
|
user_description={UDESCRIPTION}
|
|
side={SIDE}
|
|
x={X}
|
|
y={Y}
|
|
[modifications]
|
|
{TRAIT_LOYAL}
|
|
[/modifications]
|
|
[/unit]
|
|
#enddef
|
|
|
|
#define UNDEAD_UNIT TYPE SIDE X Y
|
|
[unit]
|
|
type={TYPE}
|
|
side={SIDE}
|
|
x={X}
|
|
y={Y}
|
|
[modifications]
|
|
{TRAIT_UNDEAD}
|
|
{TRAIT_LOYAL}
|
|
[/modifications]
|
|
[/unit]
|
|
#enddef
|
|
|
|
#define PLACE_IMAGE IMAGE_FILE X Y
|
|
[item]
|
|
x={X}
|
|
y={Y}
|
|
image={IMAGE_FILE}
|
|
[/item]
|
|
#enddef
|
|
|
|
#define TREMOR
|
|
[sound]
|
|
name="rumble.ogg"
|
|
[/sound]
|
|
[scroll]
|
|
x=5
|
|
y=0
|
|
[/scroll]
|
|
[scroll]
|
|
x=-10
|
|
y=0
|
|
[/scroll]
|
|
[scroll]
|
|
x=5
|
|
y=5
|
|
[/scroll]
|
|
[scroll]
|
|
x=0
|
|
y=-10
|
|
[/scroll]
|
|
[scroll]
|
|
x=0
|
|
y=5
|
|
[/scroll]
|
|
#enddef
|
|
|
|
|
|
# a macro to define a common set of magenta color values which different
|
|
# units can be color shifted by using the team color system
|
|
|
|
#define MAGENTA_IS_THE_TEAM_COLOR
|
|
flag_rgb=magenta
|
|
#enddef
|
|
|
|
|
|
# Music macros. As of 1.1.3, music is parsed as follows:
|
|
# 1. the [scenario]-level [music] tag
|
|
# 2. the [story]-level music key
|
|
# 3. any [event]-level [music] tags
|
|
#
|
|
# If you change the music at a lower level, the tags above it will NOT be re-parsed
|
|
# and your scenario will sound wrong. For example, if you set scenario music
|
|
# with the normal [scenario]-level music tag but change the music during the [story],
|
|
# it is never reset back to normal. Therefore, these macros are intended to catch
|
|
# instances like that. Of course, if you want something more elaborate, code it
|
|
# manually.
|
|
|
|
|
|
# A macro to define a standard playlist suitable for any level. The music is defined
|
|
# twice to catch instances where music is changed in a story and not set back.
|
|
|
|
#define DEFAULT_MUSIC_PLAYLIST
|
|
[music]
|
|
name=gameplay01.ogg
|
|
ms_before=12000
|
|
[/music]
|
|
[music]
|
|
name=gameplay02.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[music]
|
|
name=gameplay03.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[music]
|
|
name=main_menu.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[music]
|
|
name=wesnoth-1.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[music]
|
|
name=wesnoth-2.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[event]
|
|
name=prestart
|
|
[music]
|
|
name=gameplay01.ogg
|
|
ms_before=12000
|
|
[/music]
|
|
[music]
|
|
name=gameplay02.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[music]
|
|
name=gameplay03.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[music]
|
|
name=main_menu.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[music]
|
|
name=wesnoth-1.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[music]
|
|
name=wesnoth-2.ogg
|
|
ms_before=12000
|
|
append=yes
|
|
[/music]
|
|
[/event]
|
|
#enddef
|
|
|
|
#
|
|
# This music macro ensures that the correct music is selected
|
|
# for a scenario just in case it is changed by [story].
|
|
# It should be positioned at the top of the scenario file
|
|
# so it can be overridden by other prestart or start events.
|
|
#
|
|
# It also allows for the convenient use of a standardized
|
|
# intra-scenario music, should we decide to use one.
|
|
#
|
|
|
|
#define SCENARIO_MUSIC MUSIC
|
|
[music]
|
|
name="wesnoth-2.ogg"
|
|
[/music]
|
|
[event]
|
|
name=prestart
|
|
[music]
|
|
name={MUSIC}
|
|
[/music]
|
|
[/event]
|
|
#enddef
|
|
|
|
#define COLOR_HEAL
|
|
green=255
|
|
#enddef
|
|
|
|
#define COLOR_HARM
|
|
red=255
|
|
#enddef
|
|
|
|
#define COLOR_WHITE
|
|
red=255
|
|
green=255
|
|
blue=255
|
|
#enddef
|
|
|