Distant Lands

  Main Menu

· Home
· About DL
· Roleplaying
· Library
· Forums
· Art Gallery
· Photo Gallery
· Links
· Online Help

· Play Now!



What is a DL Macro?

Only Staff have the ability to create macros, and even then only on the
build server.

In its simplest form, a macro is just a list of DL commands. On a deeper
level, it allows for much more interactive NPCs, Rooms, Items, and in the
end, the over all playing environment. Macros give us the ability to
execute a list of commands on nearly any character under a host of different
circumstances. Add in the ability to execute commands that normally
cannot be executed, and many more possibilities are available.

If you execute the "macros" command alone, you are provided with a list
of the global macros. At this point (and it will likely not stay this
way) all macros are global, meaning anyone with access to macros can view
or modify them. Please do not modify other people's macros.

> macros

Global Macro Libraries
------------------------
#1 Test Library
------------------------

To view the macros in a library, use the macros command along with the
library number.

> macros 1

Macros from library #1 - Test Library
---------------------------------------
#1 Speed Test
---------------------------------------

If you'd like to create your own macro library (please do!) you can do so
with the macros library command like so:

> macros library <new library name>

Currently, you can create as many libraries as you desire, please don't
go crazy with them though, especially since you probably cannot delete them.
To view a macro in a library, you'll use macros show along with the
associated library and macro number.

> macros 1 show 1

#1 Speed Test
---------------
1 > mecho You begin to feel as if you've lost control of your body.
2 > mecho Something is controlling you! You feel your mouth begin to move.
3 > 'This is a macro speed test!
4 > 'Oh dear, a macro is controlling me!
5 > speed 1
6 > 'It can make me talk really fast.
7 > 'So fast that it is difficult to keep up with.
8 > 'Which I suppose could have its purposes...
9 > speed 20
10 > 'Or it could talk slower, like this.
11 > 'Which is much easier to keep up with if you are trying to read along.
12 > 'Slow enough that everyone can read it as long as the room is relatively calm.
13 > smile
14 > bow
15 > 'It can make me do more than talk!
16 > 'This is the end of the macro speed test.
17 > speed 1
18 > mecho The force that was controlling your body seems to have left.

This macro has a couple of examples of the "extra" commands, I referenced
above. Most notably mecho (macro echo -- echos a message to anyone the macro
is played upon) and speed (adjusts the speed of the macro playback -- speed
of 8-10 is approx. 1 second between each command, speed 0 is immediate).
These commands are only available when you are recording, editing, or playing a
macro.

To start recording a macro, you'll use the macro record command along with
the library number and the name of the macro like this (then you'll start
entering commands as I do -- note the prompt change, this allows for editing):

> macros 1 record Yet Another Test Macro

Now recording macro "Yet Another Test Macro".

1 Command> 'This is a test macro?

You say, 'This is a test macro?'

1 Last --> 'This is a test macro?
2 Command> 'Yes, and people are reading this, so I'm not talking to myself.

You say, 'Yes, and people are reading this, so I'm not talking to myself.'

2 Last --> 'Yes, and people are reading this, so I'm not talking to myself.
3 Command> macro record

Finished recording macro "Yet Another Test Macro".

Note: To stop recording or editing, you can use macro record or
macro edit they are interchangable (and no further arguments are required
to finish). At this point, I've created a new macro that uses the say
command twice:

> macros 1

Macros from library #1 - Test Library
---------------------------------------
#1 Speed Test
#2 Yet Another Test Macro
---------------------------------------

> macros 1 show 2

#2 Yet Another Test Macro
---------------------------
1 > 'This is a test macro?
2 > 'Yes, and people are reading this, so I'm not talking to myself.

You can edit a macro in similar fashion:

> macro 1 edit 2

Editing macro "Yet Another Test Macro".

1 Next --> 'This is a test macro?
1 Command> 'Arg, yet another test macro?!

You say, 'Arg, yet another test macro?!'

1 Last --> 'Arg, yet another test macro?!
2 Next --> 'This is a test macro?
2 Command> step end

3 Last --> 'Yes, and people are reading this, so I'm not talking to myself.
4 Command> step -3

1 Next --> 'Arg, yet another test macro?!
1 Command> macro record

Finished recording macro "Yet Another Test Macro".

Here, a command was introduced that can be executed only when a macro is
being recorded or edited, but it isn't recorded in the macro -- the step
command. It is used to move around between the command when you are editing
(or recording) a macro. While editing, to insert commands, you simply type
them in.

Macros can be renamed:

> macro 1 name 2 Another Test Macro

Library #1 macro #2 has been changed to "Another Test Macro".

> macro 1 show 2

#2 Another Test Macro
-----------------------
1 > 'Arg, yet another test macro?!
2 > 'This is a test macro?
3 > 'Yes, and people are reading this, so I'm not talking to myself.

You can execute a macro (on yourself) by using the macro command with the
library number and macro number alone:

> macro 1 2

Playing macro "Another Test Macro".

>

You say, 'Arg, yet another test macro?!'

>

You say, 'This is a test macro?'

>

You say, 'Yes, and people are reading this, so I'm not talking to myself.'
Finished playing macro "Another Test Macro".

Note: When the macro is executed on a non-Staff member, they do not see
the information about the macro starting, finishing or changing speed.

You can use macro abort to stop editing/recording a macro and discard any
changes you've made and use macro unrecord to remove commands from a macro:

> macro 1 edit 2

Editing macro "Another Test Macro".

1 Next --> 'Arg, yet another test macro?!
1 Command> macro unrecord next

1 Next --> 'This is a test macro?
1 Command> step

1 Last --> 'This is a test macro?
2 Next --> 'Yes, and people are reading this, so I'm not talking to myself.
2 Command> macro unrecord last

1 Next --> 'Yes, and people are reading this, so I'm not talking to myself.
1 Command> macro abort

Macro editing/recording aborted.

Here the first 2 commands in the macro are deleted and then the change
is aborted completely.

Here is the full syntax for the macros command:

To list all the macro libraries (or all the dynamic macros that have been created
by currently playing macros with the dynamic keyword):

> macros {dynamic}

To execute a macro on yourself, you can just specify the macro you wish to
execute (if dynamic is used a library # is not used):

> macro {dynamic} <library #> <macro #>

To copy a macro to a library you are working on, use the following syntax:

> macro <library #> <macro #> copy <library #>

To delete a macro from a library you are working on, use the following syntax:

> macro <library #> <macro #> delete <macro #>

It is worth noting here that if you want to delete a macro, for the most part,
this is not the way to do it (if you want to delete a lot of macros, talk to
an Implementor). It is a multi-step process to help ensure that you don't
accidentally delete a macro you don't mean to. In order to delete a macro, just
edit the macro and delete all of the macros contents and it will magically
disappear when you exit (with macro edit or macro record).

In order to start editing an existing macro:

> macro <library #> <macro #> edit

In order to create a new (or change an existing if you specify a library #)
macro library:

> macro <library #> library <library name>

To move a macro from one library to another:

> macro <library #> <macro #> move <library #>

To change a macro name:

> macro <library #> <macro #> name <macro name>

To play a macro on yourself or an optional target (typically for testing,
not for playing a macro within a macro, see the play command for that):

> macro <library #> <macro #> play <victim>

To begin recording a new macro, as you've seen above:

> macro <library #> record <macro name>

To view the current contents of a macro (or what you are editing/recording
if no numbers are provided):

> macro <library #> <macro #> show {nopage}

To quit editing or recording a macro without saving any of the changes
you've made:

> macro abort

Once a macro is playing, you can view it in the macro playlist, a little
more information is supplied if you provide the specific number in the playlist.
You can also optionally supply the abort keyword to end a macro being played.

> macro playlist <#> {abort}

To delete lines from a macro you are recording or editing, use macro unrecord
(* denotes to delete all lines, otherwise if # lines is omitted, 1 is assumed):

> macro unrecord <next | last | *> <# lines>

So a macro is just a bunch of DL commands, it is worth noting that some commands
work better than others (we have some commands written in an "old" style that will
be limiting initially). Additionally, we have a new set of commands that are only
available during a macro. Here is a list of those commands and their use:

To make a comment in a macro, start the line with a # followed by your comment:

> #<comment text>

You can easily make several different checks and/or adjustments for NPC
aggression towards PCs. This is done with the aggressive command.
When you use the aggressive command, a system variable is automatically
created named AGGRESSIVE which contains "Yes" for a positive response and
"No" for a negative response.

So using this we can check to see if the character the macro is running on
is flagged as aggressive:

> aggressive
> say Am I aggressive? :AGGRESSIVE:

You can also change the general (towards all PCs) aggressive:

> aggressive [ on | off ]

If the NPC has memory, it may have aggression towards a specific PC,
you can test this in much the same way we tested above, but you include
the name:

> aggressive <player name>
> say Am I aggressive towards that player? :AGGRESSIVE:

Naturally, you can also turn it on or off for specific players (if the
NPC doesn't have memory, it is turned on automatically):

> aggressive <player name> [ on | off ]

You can also adjust aggression for alignment and sex:

> aggressive [ evil | female | good | male | neutral ] [ on | off ]

To send a message to the area surrounding the character the macro is being
played upon or a message to a specific set of rooms, you can use the
area echo command.

This specifies the raw room numbers to echo a message to:

> area echo <start room #> <end room #> <echo message>

This specifies a radius, surrounding the character the macro is being played
upon, of rooms to send a message to:

> area echo rooms <num rooms> <echo message>

While writing macros, you can use the capture command to get information
about a character, item or room in local proximity to the macro. That is to say, 
information about a character or item in the room with the character which
has the macro being played as well as the inventory and equipment list of the
character the macro is being played upon.  Additionally, you can find out some
information about the room the character is in (typically will be used with
the string command):

> capture room [ description | name ]

To capture description and naming information about a NPC (for use with
string typically):

> capture npc <character in room> [ description | namelist | short | long ]

Items work in a similar fashion:

> capture item <item in room, inventory or equiped> [ namelist | short | long ]

A careful reader at this point will likely have come up with the question...

I execute these commands in my script, for example I might use something like
capture item dagger short to find out the short description of the dagger
currently being wielded by the character the macro is playing upon, but then
where does this information go?  How do I access it?

The answer is it is put into the system variable CAPTURE, which you will typically
want to capture yourself in a variable, for example:

> capture item dagger short
> * dynamic variable create dagger_short :CAPTURE:

Many other attributes beyond descriptions and naming information can be obtained.
The following are available to capture information about a character in the room:

> capture alignment [permanent | real] <character in room>
> capture class <character in room>
> capture damroll <character in room>
> capture full <character in room>
> capture gold <character in room>
> capture height <character in room>
> capture hit points <character in room>
> capture hitroll <character in room>
> capture hunger <character in room>
> capture level <character in room>
> capture mana <character in room>
> capture move <character in room>
> capture position <character in room>
> capture power <character in room>
> capture practices <character in room>
> capture race <character in room>
> capture song <character in room>
> capture tame <character in room>
> capture thirst <character in room>
> capture wait <character in room>
> capture weight <character in room>
> capture max hit <character in room>
> capture max mana <character in room>
> capture max move <character in room>
> capture max power <character in room>
> capture max song <character in room>

You can also capture the unique identifier of a character or item:

> capture uid <character in room | item in inventory, room, or equiped>

Finally, there is also a short cut to the capture command, much like the dynamics
command uses *, you can replace capture with +.  So our previous dagger short
description capture could have been written:

> + item dagger short
> * dynamic variable create dagger_short :+:

Once you've captured some information, or maybe you just want to adjust something
specific, you can use the change command to modify different character's attributes:

> change position <character in room> <value>
> change [ relative ] alignment [ permanent | real ] <character in room> <value>
> change [ relative ] damroll <character in room> <value>
> change [ relative ] full <character in room> <value>
> change [ relative ] gold <character in room> <value>
> change [ relative ] height <character in room> <value>
> change [ relative ] hit points <character in room> <value>
> change [ relative ] hitroll <character in room> <value>
> change [ relative ] hunger <character in room> <value>
> change [ relative ] mana <character in room> <value>
> change [ relative ] move <character in room> <value>
> change [ relative ] power <character in room> <value>
> change [ relative ] practices <character in room> <value>
> change [ relative ] song <character in room> <value>
> change [ relative ] tame <character in room> <value>
> change [ relative ] thirst <character in room> <value>
> change [ relative ] wait <character in room> <value>
> change [ relative ] weight <character in room> <value>

Most of the change settings support the relative keyword meaning to adjust
the setting based upon the existing setting. Additionally, much like capture
uses + as a shortcut, change has = as a shortcut, and it also can use
the shortcut =+ for change relative. So while this would set Nezmar's
gold to 1:

> = gold nezmar 1

This would add 1 gold to Nezmar's gold:

> =+ gold nezmar 1

Because change is fairly complex, it populates multiple system variables
which you might wish to use.  Specifically FROM contains what the setting was
before being changed and TO contains the new setting.  Further, CHANGE contains
a string description of the change, this might be useful for troubleshooting.

You can add delay to a character with the delay command and the associated
number of seconds until the character's input should be accepted:

> delay self 5

If there is an item or NPC that you wish to silently destroy you can do so with
the destroy command. It works on either an item in the inventory of the character
the macro is being played upon or a non-player character in the room with the
character the macro is being played upon. If the argument provided is a NPC, the
NPC will only disappear when nobody is in the room. If the argument provided is
an item in inventory, the item is destroyed instantly.

> destroy <item in inventory | character in room>

There is no question if want to write interactive macros, you'll need to understand
dynamics. They allow you to do a host of different things, so many, they it
gets its own help file.

> dynamics

You can use the each command to iterate through a list or count for
example, if you have a list named fruit and you want step through each
member and say its entry you might do:

> each fruit
>   say :EACH:

Yes, just like capture, each puts information about the current iteration
in a system variable with the same name. Additionally, each can be used with
braces like if and else. While an each is being performed, if you'd like to
stop the loop you can use the break command. If you want to skip the rest
of the loop and go to the next iteration, you can do so with the continue
command. If a number is provided, each will count up to that number starting
from 1.  For example, this would have the character the macro is playing on
say 1, say 2, skip 3, say Hello World! instead of 4 and then break out of the
loop instead of saying 5:

> each 5 {
>   if :EACH: = 3
>     continue
>   if :EACH: = 5
>     break
>   if :EACH: = 4
>     say Hello World!
>   else
>     say :EACH:
> }

The if command is used to execute a command or set of commands under
a specific condition. It can be used with a { opening brace to denote
that it will utilize multiple lines. Additionally, after the first if has
been declared, the else command can be used to execute commands under
alternate conditions. The else command can be combined with both {
opening } and closing braces, as well as an if command.

The if command can be used to test to see if variables or lists have
been defined:

> if <variable_name | list_name | SYSTEM_VARIABLE>

Or it can be used to see if a variable or list doesn't exist:

> if no <variable_name | list_name | SYSTEM_VARIABLE>

To perform tests against numbers, you can use the equal (=), not equal (!=),
greater than (>), less than (<), equal to or greater than (>=), and equal
to or less than (<=). See math below for more information about how to
manipulate numbers.

For example to test if two numbers are equal (and if they are, execute the
next command, if not, skip it):

> if <number1> = <number2>

Or to test to see if a number is greater than or equal to another number and
then execute multiple lines if it is (you don't have to add the 2 spaces in
front of lines 2 and 3 like I do, but it is advised because it makes it easier
to read):

> if <number1> >= <number2> {
>   say line 1
>   say line 2
> }

Especially if you have nested if statements (which I also typically try to
line up using 2 space indents for reading purposes):

> if <number1> >= <number2> {
>   if <number1> = <number2>
>     say number1 and number2 are equal
>   else {
>     say number1 is greater than number2
>     say number1 is bigger, number2 is smaller
>   }
> }

As previously stated, you can combine if with else to test a series
of conditions, for example:

> if <number1> > <number2>
>   say number 1 is greater than number 2
> else if <number1> = <number2>
>   say number 1 is equal to number 2
> else
>   say number 1 must be less than number 2

In addition to numbers, you can compare different sets of characters for
a specific condition. This can be done using combinations of fixed strings,
variables, lists, and system variables. Fixed strings are any set of characters
between a set of double quotes (with the exception of the double quotes
themselves). So to perform a case sensitive comparision between two fixed
strings (which in this case will always be false):

> if "test" <-> "TEST"

Or if you wanted this comparision to be true (so it would execute the next
line), you could make it case insensitive:

> if "test" <=> "TEST"

Or if you wanted this comparision to be false, but you still wanted it
to be case insensitive you could use the "not" operator. Typically
you'd be doing this with some variable or system variable (here we check
to make sure the LOCATE system variable does not match the word room or
we skip the next line if it does):

> if "room" <!=> LOCATE

Using the if command you can also to see if a string is contained
within another string (this would always be true):

> if "This is a room." <> "room"

Again there is also a "not" version of it which would always be false
(and thus skip the next line):

> if "This is a room." <!> "room"

If it isn't clear already, these can also be used to match variables,
lists and system variables. Typically you'll find some combination
of these useful for different situations. It is worth noting that a
list is considered a specific type of variable for these tests and
if any part of the list matches the criteria provided, it should have
the desired effect. For example, if one of the list members matches a
specific string that it is being compared to, the statement would be
considered true (unless it was a not!).

You can find out information about the location of a character or item with
the locate command:

> locate <character | item>

The information will be provided in the system variable LOCATE.  If a character
name is provided, it will contain the word "room" the character is in the same
room as the character the macro is executed on, otherwise it will have the room
number they are in, if it is available, if all else fails (because they are dead
or something, for example), it will contain the word "world".  If an item name
is provided, LOCATE will contain "room", "inventory" or "equiped" if the item
is in the room with or in the possession of the character macro is played on.
If the item is being carried or worn by another character, it will contain the
name of the character as well as "(carried)" or "(worn)". If the item is in a
different place, it will use "world".

So, as an example, if we wanted to see if we have a crown that we load with
currently equiped (or inventory) we might do something like this:

> locate crown
> if LOCATE <> "equiped"
>   say Have you seen my crown?  Isn't it beautiful?!
> else if LOCATE <!> "inventory"
>   say Have you seen my crown?  WHERE IS MY CROWN?!

You can instantly, without any messages move the character the macro is playing
on (or a target in the room based upon keyword) to any room with the location
command.

> location <victim> <room #>

Changing numbers around with the math command is both simple and very basic.
When you provide the math command with 2 numbers and an operation (such as
+, -, /, or x) it populates the system variable MATH with the answer. So, if we
wanted to double a dynamic variable we created previously we might do something
like this:

> math :my_num: x 2
> dynamic variable update my_num :MATH:

It is probably worth noting that divide by zero just returns 0.

The command mecho allows you to send a message to the character that the
macro is currently being played on.

> mecho <echo message to macro target>

The mrecho command allows you to send a message to the room of the character
that the macro is currently being played on.

> mrecho <echo message to macro target & room>

The nmrecho command allows you to send a message to the room of the character
that the macro is currently being played on without sending that message to the
character the macro is playing on.

> nmrecho <echo message to macro room (but not macro target)>

The pause command pauses a macro recording or editing you are currently
performing and drops you to a regular prompt that will not be recorded.
To resume, you execute the pause command again.

> pause

To play another macro (or a dynamic macro) within a macro, use the play
command (no library # is needed to play a dynamic macro):

> play {dynamic} <library #> <macro #>

The random command populates the system variable RANDOM number
between 1 and the number provided (or between the 2 numbers provided
if 2 are given). For example to pick a random number between 10 and
20 and then capture it into a variable named my_num we would do this:

> random 10 20
> dynamic variable create my_num :RANDOM:

You can change a NPC to being a scavenger (picking up lying around items) or
not with the scavenger command. Because it populates the system variable
SCAVENGER with "yes" or "no" you can also check to see what it is currently
set to if you use the command with no arguments.

> scavenger [ on | off ]

You can change a NPC from wandering to stationary with the sentinel
command. Because it populates the system variable SENTINEL with "yes" or "no"
you can also check to see what it is currently set to if you use the command
with no arguments.

> sentinel [ on | off ]

It is possible to create both items and NPCs (mobs) using the spawn
command with an optional message:

> spawn [ item | npc ] <#> <spawn message - $n, etc.>

It is possible to spawn items and NPCs in a specific room:

> spawn item <#> room <# | current> <spawn message - $n, etc.>
> spawn npc <#> room <#> <spawn message - $n, etc.>

The spawn command creates a system variable named SPAWN that continues
the UID (unique identifier) of the item or NPC created.

Changing the speed allows you to change the speed with which the macro is
played back. The default speed is 3. A speed of 8-10 typically plays back
about 1 command per second. A speed of 0 means immediate (each command will
be executed until a speed change is made or the script is completed).

> speed <#>

The step command is used during recording and editing only, so step commands
are not themselves recorded. Step allows you to move through a recording so that
you can inject commands where you want them. Using the command by itself will
advance 1 line (same as step 1) and you can specific a relative line number (-2
would go back 2 lines for example).

> step <# | beginning | ending>

The time command can be used in a macro to capture information about the
current time in DL.  It is used by itself and it creates several system variables
which contain the information: HOUR, WEEKDAY, DAY, MONTH, MONTH_NAME, and YEAR.

> time

The wait command is very versatile and easy to use. It allows you to inject
pauses in macro playback. If you use wait forever it will exit the editor
because it assumes you are done editing the macro (what more can you want to do?).
Otherwise, the numbers provided are dependant upon the keywords you provide.
If you do not specify any keywords, it expects only 1 number and it will wait
an amount of time dependant upon current macro execution speed. With the default
speed of 3, each wait unit is roughly equivalent to 1/2 second. If you use
wait random it will take either 1 or 2 numbers. If you provide 1 number it
will wait a random time between 1 and the number you provide wait units
(as described above). If you provide 2 numbers, it will wait a random time
between the 2 wait units specified. If you use the trigger dynamic keywords,
it will wait until the dynamic trigger specified is triggered before moving on
to play the rest of the script.

> wait [default | forever | random | trigger {dynamic}] <#> <#>

It is also worth noting that a some other commands have been modified to work
better with macros. More specifically, track and consider both provide system
variables with feedback from the results of the command. The string command has
been modified to work within macros as well.

See Also:  Dynamics
Back to Distant Lands Help Help Master Keyword Index List
  Recent Posts

 
  W3C Validation
Valid XHTML 1.0 Strict Valid CSS!

Website layout and design by .
DHTML Menu By Milonic JavaScript