FloodWML

From The Battle for Wesnoth Wiki
Revision as of 09:55, 21 August 2011 by Lipk (talk | contribs) (Creating floods)

Usage

You can find sources at the bottom of the page. It's too long to include it here. NOTE: these macros are performing lots of complex calculations thus they are quite slow. They can make your scenario lag and so make a serious blow especially on older machines. To make sure you've minimized the negative effects, please read the Optimization section below.

To create a flood:

{CREATE_FLOOD "1,1;2,3" "ne,n" "Gg>Ww;Gs>Wwt" awesome_flood}

Where "1,1;2,3" is a semicolon separated list of coordinate pairs where the flood starts from, "ne,n" is a comma separated list of directions in which the flood will spread, "Gg>Ww;Gs>Wwt" is a semicolon separated list of transformations where a>b means that the hexes with the terrain code a will be converted to b, and finally awesome_flood is the variable to store the current state of the flood in (but you might better think about it as the flood's id).

To spread a flood by one hex:

{SPREAD_FLOOD awesome_flood}

Where awesome_flood is the flood's id :)

To modify a flood's data:

{SET_FLOOD_DIRECTIONS "se,s" awesome_flood}
{SET_FLOOD_TERRAIN_TABLE "Gg>Wwg;Gs>Ww" awesome_flood}
{SET_FLOOD_SOURCE "3,3;5,4;6,6" awesome_flood}

One note: all of these macros replace current data in awesome_flood, so old information is lost. This is especially important for SET_FLOOD_SOURCE because that alters the list of hexes which are currently form the first wave of the flood. So if you call it, the original flood will stop and a new one will start from "3,3;5,4;6,6" or whatever you specify.

Optimization

When to do it?

The part consuming up most of the macro's run time is choosing the appropriate terrain type to convert the original to. If you have a wide-spreading flood, this will have to be done for many hexes. Conclusively, if you have a big flood with a big terrain table, it's likely that you'll have to optimize it.

Source Code

#define INVERT_DIRECTIONS DIRECTIONS OUT_VAR
	#a macro to change directions to their opposites (n->s, sw->ne, etc)
	#DIRECTIONS is a comma-separated list of directions
	#OUT_VAR is the variable to write the output in. Output is an array
	#which contains the inverted directions in the order they were given
	#in DIRECTIONS. The values are stores in the 'direction' key.

[set_variables]
	name={OUT_VAR}
	[split]
		list={DIRECTIONS}
		separator=","
		key=direction
		remove_empty=yes
	[/split]
[/set_variables]

{FOREACH {OUT_VAR} TMP_ID_i}
	[if]
		[variable]
			name={OUT_VAR}[$TMP_ID_i].direction
			equals="n"
		[/variable]
		[then]
			[set_variable]
				name={OUT_VAR}[$TMP_ID_i].direction
				value="s"
			[/set_variable]
		[/then]
	[else]
	[if]
		[variable]
			name={OUT_VAR}[$TMP_ID_i].direction
			equals="s"
		[/variable]
		[then]
			[set_variable]
				name={OUT_VAR}[$TMP_ID_i].direction
				value="n"
			[/set_variable]
		[/then]
	[else]
	[if]
		[variable]
			name={OUT_VAR}[$TMP_ID_i].direction
			equals="se"
		[/variable]
		[then]
			[set_variable]
				name={OUT_VAR}[$TMP_ID_i].direction
				value="nw"
			[/set_variable]
		[/then]
	[else]
	[if]
		[variable]
			name={OUT_VAR}[$TMP_ID_i].direction
			equals="nw"
		[/variable]
		[then]
			[set_variable]
				name={OUT_VAR}[$TMP_ID_i].direction
				value="se"
			[/set_variable]
		[/then]
	[else]
	[if]
		[variable]
			name={OUT_VAR}[$TMP_ID_i].direction
			equals="ne"
		[/variable]
		[then]
			[set_variable]
				name={OUT_VAR}[$TMP_ID_i].direction
				value="sw"
			[/set_variable]
		[/then]
	[else]
	[if]
		[variable]
			name={OUT_VAR}[$TMP_ID_i].direction
			equals="sw"
		[/variable]
		[then]
			[set_variable]
				name={OUT_VAR}[$TMP_ID_i].direction
				value="ne"
			[/set_variable]
		[/then]
	[/if]
	[/else]
	[/if]
	[/else]
	[/if]
	[/else]
	[/if]
	[/else]
	[/if]
	[/else]
	[/if]
{NEXT TMP_ID_i}

#enddef

#define STORE_FLOODABLE_LOCATIONS SOURCE_X SOURCE_Y DIRECTIONS TERRAINS OUT_VAR
	#stores hexes of type TERRAINS whose neighbour in one of DIRECTIONS directions is one of SOURCE_X ; SOURCE_Y
	#SOURCE_X & SOURCE_Y comma-separated list of coordinates
	#DIRECTIONS an array of directions, values stored in the 'direction' key (same as the output format of INVERT_DIRECTIONS)
	#TERRAINS comma-separated list of terrain codes
	#OUT_VAR the variable to write the output in
	#
	#NOTE: this macro is in fact used to store the hexes of type TERRAINS which are neighbours of SOURCE_X ; SOURCE_Y in
	#certain directions, but we achieve that by inverting those directions outside of this macro. See INVERT_DIRECTIONS.

[store_locations]
	variable={OUT_VAR}

	terrain={TERRAINS}

	[filter_adjacent_location]
		adjacent=${DIRECTIONS}[0].direction
		x={SOURCE_X}
		y={SOURCE_Y}
	[/filter_adjacent_location]
	[or]
	terrain={TERRAINS}
		
	[filter_adjacent_location]
		adjacent=${DIRECTIONS}[1].direction
		x={SOURCE_X}
		y={SOURCE_Y}
	[/filter_adjacent_location]
	[or]
	terrain={TERRAINS}
		
	[filter_adjacent_location]
		adjacent=${DIRECTIONS}[2].direction
		x={SOURCE_X}
		y={SOURCE_Y}
	[/filter_adjacent_location]
	[or]
	terrain={TERRAINS}
		
	[filter_adjacent_location]
		adjacent=${DIRECTIONS}[3].direction
		x={SOURCE_X}
		y={SOURCE_Y}
	[/filter_adjacent_location]
	[or]
	terrain={TERRAINS}
		
	[filter_adjacent_location]
		adjacent=${DIRECTIONS}[4].direction
		x={SOURCE_X}
		y={SOURCE_Y}
	[/filter_adjacent_location]
	[or]
	terrain={TERRAINS}
		
	[filter_adjacent_location]
		adjacent=${DIRECTIONS}[5].direction
		x={SOURCE_X}
		y={SOURCE_Y}
	[/filter_adjacent_location]
	[/or]
	[/or]
	[/or]
	[/or]
	[/or]

[/store_locations]
#enddef


#define SPLIT_PAIRS PAIRS SEP1 SEP2 OUT_VAR
[set_variables]
	name=TMP_pairs
	[split]
		list={PAIRS}
		key=pair
		separator={SEP1}
		remove_empty=true
	[/split]
[/set_variables]

{FOREACH TMP_pairs TMP_SP_i}
	[set_variables]
		name=TMP_splitted
		[split]
			list=$TMP_pairs[$TMP_SP_i].pair
			separator={SEP2}
			key=value
		[/split]
	[/set_variables]

	[set_variable]
		name={OUT_VAR}[$TMP_SP_i].value1
		value=$TMP_splitted[0].value
	[/set_variable]
	[set_variable]
		name={OUT_VAR}[$TMP_SP_i].value2
		value=$TMP_splitted[1].value
	[/set_variable]
{NEXT TMP_SP_i}

{CLEAR_VARIABLE TMP_pairs}
{CLEAR_VARIABLE TMP_splitted}
#enddef

#define FLOOD_SINGLE_HEX X Y TERRAIN_TABLE
[store_locations]
	variable=TMP_current_hex
	x={X}
	y={Y}
[/store_locations]

{FOREACH {TERRAIN_TABLE} FSH_i}
	[if]
		[variable]
			name=TMP_current_hex.terrain
			equals=${TERRAIN_TABLE}[$FSH_i].value1
		[/variable]
		[then]
			{MODIFY_TERRAIN ${TERRAIN_TABLE}[$FSH_i].value2 {X} {Y}}
			[set_variable]
				name=FSH_i
				value=${TERRAIN_TABLE}.length
			[/set_variable]
		[/then]
	[/if]
{NEXT FSH_i}


{CLEAR_VARIABLE TMP_current_hex}
#enddef

#define SET_FLOOD_TERRAIN_TABLE TERRAIN_TABLE DATA_VAR
{SPLIT_PAIRS {TERRAIN_TABLE} ";" ">" {DATA_VAR}.terrain_table}
[set_variable]
	name={DATA_VAR}.floodable_terrains
	[join]
		variable={DATA_VAR}.terrain_table
		separator=","
		key=value1
	[/join]
[/set_variable]
#enddef

#define SET_FLOOD_DIRECTIONS DIRECTIONS DATA_VAR
{INVERT_DIRECTIONS {DIRECTIONS} {DATA_VAR}.directions}
#enddef

#define SET_FLOOD_SOURCE SOURCE DATA_VAR
{SPLIT_PAIRS {SOURCE} ";" "," TMP_source_coordinates}
[set_variable]
	name={DATA_VAR}.fields_x
	[join]
		variable=TMP_source_coordinates
		key=value1
		separator=","
	[/join]
[/set_variable]
[set_variable]
	name={DATA_VAR}.fields_y
	[join]
		variable=TMP_source_coordinates
		key=value2
		separator=","
	[/join]
[/set_variable]
#enddef

#define CREATE_FLOOD SOURCE DIRECTIONS TERRAIN_TABLE DATA_VAR
[clear_variable]
	name={DATA_VAR}
[/clear_variable]

{SET_FLOOD_SOURCE {SOURCE} {DATA_VAR}}
{SET_FLOOD_TERRAIN_TABLE {TERRAIN_TABLE} {DATA_VAR}}
{SET_FLOOD_DIRECTIONS {DIRECTIONS} {DATA_VAR}}
#enddef

#define SPREAD_FLOOD DATA_VAR
{STORE_FLOODABLE_LOCATIONS ${DATA_VAR}.fields_x ${DATA_VAR}.fields_y {DATA_VAR}.directions ${DATA_VAR}.floodable_terrains TMP_floodable}

{FOREACH TMP_floodable TMP_SF_i}
	{FLOOD_SINGLE_HEX $TMP_floodable[$TMP_SF_i].x $TMP_floodable[$TMP_SF_i].y {DATA_VAR}.terrain_table}
{NEXT TMP_SF_i}
[redraw][/redraw]

[set_variable]
	name={DATA_VAR}.fields_x
	[join]
		variable=TMP_floodable
		key=x
		separator=","
	[/join]
[/set_variable]
[set_variable]
	name={DATA_VAR}.fields_y
	[join]
		variable=TMP_floodable
		key=y
		separator=","
	[/join]
[/set_variable]
#enddef