New macros for utils.cfg?
Moderator: Forum Moderators
Forum rules
- Please use [code] BBCode tags in your posts for embedding WML snippets.
- To keep your code readable so that others can easily help you, make sure to indent it following our conventions.
New macros for utils.cfg?
I'd like to see a few macros added to utils.cfg. Here are the best ones, which I use in all of my UMCs:
This is used to ACTUALLY move a unit, instead of just drawing the moving sprite. You input the unit's current coordinates, then any hexes you want him to visit (if they're not on the default path), then the destination. It will store him, move_unit_fake his unit type to the new location, and then unstore him in that location. VERY useful. I use it constantly. (I haven't tested, but it might be possible to optimize it by using [teleport] instead of [store_unit], [set_variable], and [unstore_unit].)
Formatting variables is needed in certain situations, especially when you are storing arrays of units and then iterating over the array.
Code: Select all
#define MOVE_UNIT_FAKE X1 Y1 XM YM X2 Y2
[store_unit]
[filter]
x,y={X1},{Y1}
[/filter]
variable=temp
kill=yes
[/store_unit]
[move_unit_fake]
x={X1},{XM},{X2}
y={Y1},{YM},{Y2}
type=$temp.type
[/move_unit_fake]
[set_variable]
name=temp.x
value={X2}
[/set_variable]
[set_variable]
name=temp.y
value={Y2}
[/set_variable]
[unstore_unit]
variable=temp
[/unstore_unit]
[clear_variable]
name=temp
[/clear_variable]
[redraw]
[/redraw]
#enddef
Code: Select all
#define FORMAT VARIABLE TEMP_VARIABLE ELEMENT
[set_variable]
name={VARIABLE}_{TEMP_VARIABLE}_{ELEMENT}
to_variable={VARIABLE}[${TEMP_VARIABLE}].{ELEMENT}
[/set_variable]
#enddef
#define FOREACH_FORMAT VARIABLE TEMP_VARIABLE
{FOREACH {VARIABLE} {TEMP_VARIABLE}}
{FORMAT {VARIABLE} {TEMP_VARIABLE} x}
{FORMAT {VARIABLE} {TEMP_VARIABLE} y}
#enddef
For I am Turin Turambar - Master of Doom, by doom mastered. On permanent Wesbreak. Will not respond to private messages. Sorry!
And I hate stupid people.
The World of Orbivm
And I hate stupid people.
The World of Orbivm
The first is possible shorter:
In general, these macros could be useful, yes.
Code: Select all
#define MOVE_UNIT_FAKE X1 Y1 XM YM X2 Y2
[hide_unit]
[filter]
x,y={X1},{Y1}
[/filter]
[/store_unit]
[move_unit_fake]
x={X1},{XM},{X2}
y={Y1},{YM},{Y2}
type=$temp.type
[/move_unit_fake]
[teleport]
x={X2}
y={Y2}
[filter]
x={X1}
y={Y1}
[/filter]
[/teleport]
[unhide_unit]
x={X2}
y={Y2}
[/unhide_unit]
[redraw]
[/redraw]
#enddef
First read, then think. Read again, think again. And then post!
Generally I'm in favour of adding as much useful macros to utils.cfg as possible. They don't really take up any space and it's somewhat dumb to have to manually copy all the useful macros to your campaign/whatever while the utils.cfg is full of mostly useless and messy macros. So, in addition to the ones below, I'd favour adding things like STORE_UNIT_VAR, PUT_TO_RECALL_LIST, and the like.
I constantly use MODIFY_UNIT. IMHO it's very useful.
Also, personally I'd prefer a version of MOVE_UNIT that accepts a standard unit filter instead of only coordinates. And yes, it can be written shorter and all that, but I think description= based (for example) filters are usually somewhat cleaner to use.
Checking for a terrain in a certain location is also very cumbersome, so IF_TERRAIN (or some variant) would be good to have, too.
I constantly use MODIFY_UNIT. IMHO it's very useful.
Code: Select all
# 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
Code: Select all
# 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
Code: Select all
# 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
The X_in_between and y_in_between are often useful, so I'd like to leave them. If you don't want to use them, just have them the same as the X2, Y2...
For I am Turin Turambar - Master of Doom, by doom mastered. On permanent Wesbreak. Will not respond to private messages. Sorry!
And I hate stupid people.
The World of Orbivm
And I hate stupid people.
The World of Orbivm
Wouldn't findvacant=yes be a better default behavior? And, if it's really moving the unit, why call it fake?
Also, the FORMAT macro seems poorly named. It's not using the format feature-- it's accessing elements from arrays and re-storing them in toplevel variables. Although this may be a useful hack for avoiding situations with simple variable expansion, I wouldn't even encourage people to use it regularly since it increases variable clutter.
Also, the FORMAT macro seems poorly named. It's not using the format feature-- it's accessing elements from arrays and re-storing them in toplevel variables. Although this may be a useful hack for avoiding situations with simple variable expansion, I wouldn't even encourage people to use it regularly since it increases variable clutter.
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
It's reformatting the variable name and so that it can be used... but if anyone thinks of a better name, we can use that.Sapient wrote:Also, the FORMAT macro seems poorly named.
It's not a hack; it's the only possible way to access the variables (i.e. the only other way is to use similar code, not using the macro).Sapient wrote:Although this may be a useful hack
Because it is not an in-game move, it is WML moving the unit - so, fake. But, as you can see, zookeeper changed that. I don't care either way - changing it is probably better so it doesn't conflict with un-updated campaigns.Sapient wrote:Wouldn't findvacant=yes be a better default behavior? And, if it's really moving the unit, why call it fake?
findvacant=yes isn't necessary because zookeeper's version uses [teleport], not [unstore_unit].
BTW, does this work?:
Code: Select all
[redraw][/redraw]
Anyway, I think we should commit the macros now, argue about them later.
The modify_unit macro looks pretty useful. The if_terrain macro does too, but I don't like the syntax it uses; wouldn't this make more sense?:
Code: Select all
# 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]
# {/IF_TERRAIN}
# [/event]
#define IF_TERRAIN X Y TYPES
[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]
#enddef
#define /IF_TERRAIN
{CLEAR_VARIABLE IF_TERRAIN_temp}
[/if]
#enddef
For I am Turin Turambar - Master of Doom, by doom mastered. On permanent Wesbreak. Will not respond to private messages. Sorry!
And I hate stupid people.
The World of Orbivm
And I hate stupid people.
The World of Orbivm
It might be redundant actually in this case...turin wrote:BTW, does this work?:I've never used that.Code: Select all
[redraw][/redraw]
I can do that, unless someone else really wants to. I think I'd add MODIFY_UNIT, MOVE_UNIT, IF_TERRAIN and PUT_TO_RECALL_LIST for starters. They wouldn't be used immediately anyway, so they can be tuned more after that.turin wrote:Anyway, I think we should commit the macros now, argue about them later.
I guess it's a matter of taste really - and I unsurprisingly prefer my version (and use the same () style in my own macros whenever possible, since it's pretty).turin wrote:The modify_unit macro looks pretty useful. The if_terrain macro does too, but I don't like the syntax it uses; wouldn't this make more sense?:
PS. What the heck does the FORMAT macro do? I couldn't really see it after a minute of pondering...
FORMAT:
Personally, I'd rather manage the temp variables myself, since I will need to clear them anyway (and might wish to re-use the same variable for subsequent calls). I noticed that the version Turin posted is a bit different than the one on the wiki.
On another note, I think it may behave unexpectedly if you pass $vars in the macro arguments. However, my main objection is its name... maybe STORE_ARRAY_VAR would explain what it is doing better?
And FOREACH_FORMAT might be renamed FOREACH_STORE_XY ?
Personally, I'd rather manage the temp variables myself, since I will need to clear them anyway (and might wish to re-use the same variable for subsequent calls). I noticed that the version Turin posted is a bit different than the one on the wiki.
On another note, I think it may behave unexpectedly if you pass $vars in the macro arguments. However, my main objection is its name... maybe STORE_ARRAY_VAR would explain what it is doing better?
And FOREACH_FORMAT might be renamed FOREACH_STORE_XY ?
http://www.wesnoth.org/wiki/User:Sapient... "Looks like your skills saved us again. Uh, well at least, they saved Soarin's apple pie."
FORMAT is useful only because some tags don't expand variables... i.e., in some tags $unitname[$i].x is meaningless; you need to do the thing FORMAT does.
For I am Turin Turambar - Master of Doom, by doom mastered. On permanent Wesbreak. Will not respond to private messages. Sorry!
And I hate stupid people.
The World of Orbivm
And I hate stupid people.
The World of Orbivm