DM Reference

View the live web reference here.


DM language details

The DM (Dream Maker) language uses a syntax similar to C/C++ to build networked multi-user worlds. This reference and the accompanying guide discuss the structure and function of DM.

This reference is arranged in sections:

You can filter the reference content by subject, which helps narrow down anything you might be looking for.

In various articles you may see notes or sidebar content:

⚠️Important note
🔒️Security concerns
🏃️Performance tip
👍️Rule of thumb
🏛️Compatibility
💡️Did you know?
🔧️Under the hood
🎳️Play area

cache

See also:
FILE_DIR definition
cache_lifespan var (world)
fcopy_rsc proc
file proc
icons
sounds

Files specified in single quotes are loaded (at compile time) into the world cache file (ending in .rsc). These are referred to as resource files. At runtime these files are downloaded by players into their byond.rsc file for future use. With the appropriate verbs or through savefiles, players may also upload files into the world cache.

If a resource file is not used for a long time, it will be automatically removed from the cache file to save space. If a cache file gets too bulky, however, you may manually delete it and start from scratch.

To make compilation faster and to make it easier to distribute code, the compiler will use an existing cache file if possible. That means you could compile up a world, and send people the .dm and .rsc files without any need to package all the individual resource files. It is also possible to include additional supplementary .rsc files by using the #include statement.


comment

Comments may be used to explain code. They can also be used to turn off a line or block of code. All text inside a comment is ignored by the compiler.

The single line comment begins with // and runs to the end of the line.

The multi-line comment begins with /* and runs until */.

Multi-line comments may be nested.

Example:

// single line comment /* multi-line comment */

garbage collection

See also:
del proc
world
refcount proc

At runtime, data objects are garbage collected. That means data which is no longer in use gets automatically deleted to free up system memory. This applies to text strings, lists, savefiles, datum objects, and so on.

The garbage collector works by using an efficient reference counting system. Once an item is no longer referenced by any variable, it gets deleted. For the most part, that frees you from having to think about memory allocation, which is wonderful, especially in the case of text strings, which tend to be allocated on the fly all over the place.

There are a couple provisos that you should note. One is that circular references will never be deleted by the garbage collector. By circular reference, I mean a pair of objects with variables that point to each other, or even an object with a variable that points to itself. In rare cases, you may even depend on this behavior. When you are done with such objects, you should either null out the circular reference, or you should forcibly destroy each object with the del instruction.

An object with running or sleeping procs is referenced by the src variable of those procs and will therefore not be thrown out.

Another note is that the world.contents list does not count as a reference. Otherwise, /mob and /obj objects would never be deleted, which is not the case. Note that objects which are contained by another object or which contain objects themselves are referenced and will not be deleted. That means an object must be at loc=null with no contents and, of course, no other references anywhere in order to get deleted by the garbage collector.

Mobs with a non-empty key and all objects with non-empty tag are also immortal.

Turfs and areas do not currently get garbage collected.

When the world shuts down, all objects are destroyed, whether they are referenced or not. You don't have to worry about system memory getting consumed by persistent objects. That doesn't happen.

In general, people who do not like reference counting garbage collection should be happy that DM provides a del instruction, allowing you to take charge and delete things whether they are referenced or not. Another nicety is that this automatically nulls out any existing references to the object, so you don't end up with dangling references to a deleted object, which can otherwise be a great source of instability and mysterious bugs.


icons

See also:
FILE_DIR definition
cache
flick proc
icon
icon var (atom)
icon_state var (atom)
image objects

An icon file may be referenced by putting single quotes around the filename. The file extension determines the type of icon. Currently supported icon types are .dmi, .bmp, .png, .jpg, and .gif. To create dmi icons, use the Dream Maker icon editor. This allows you to make animations, 4 or 8 directional icons, and icons with different states (such as "live" and "dead").

Example:

mob icon = 'monster.dmi'

You can also load icons into memory at run-time and manipulate the graphical data to produce new icons dynamically. This is done by creating an /icon object.


icon arithmetic

See also:
icon proc
icon_states proc
icons
rgb proc
turn proc (applied to an icon)
icon object

Note: The following "arithmetical" methods of icon manipulation are being phased out in favor of the /icon object, which can be directly manipulated and which provides a wider variety of operations. Many of those in turn have been obviated by the color and transform vars.

There are several ways in which icons can be manipulated at runtime. They can be rotated, added together, and the colors components may be altered.

One purpose for such operations is to make players look different. Other interesting uses (and abuses) will undoubtedly follow.

Addition and Subtraction

The result of adding two icons is an arithmetic combination of the color components of each individual pixel. At positions where either icon is transparent, the result is also transparent. Subtraction, instead of increasing the intensity, decreases it by the amount in each pixel of the icon being subtracted.

Suppose you wanted to add together different bodies and heads. You could do that by making a few of each type with black backgrounds. When these add together, the black contributes nothing but prevents pixels in the other icon from getting clipped.

Example:

mob/verb addicon(I as icon) icon += I subicon(I as icon) icon -= I

If you need to add the same color to every pixel, you can do so using a color value. Color values have the same format as in HTML: "#RRGGBB" with two hexadecimal digits for each color component. That gives you a range in color from 0 to FF (which is 255 in decimal).

You can also specify a color value as "#RGB". The single digit is automatically repeated, so "#F00" is the same as "#FF0000", which is bright red. For certain pre-defined color values, you can also specify a name, such as "red". See HTML colors for a list of color names.

If you prefer base 10, you can create color values with the rgb(R,G,B) instruction. Each parameter is in the range 0 to 255.

Multiplication

To increase (or decrease) the intensity of an icon multiplicatively, you can use the '*' operator.

Example:

mob/verb/multicon(factor as num) icon *= factor

mouse handling

Various mouse actions may be handled by defining procedures either on the client object or on the atomic object being manipulated. Any of the following procedures may be defined:

In general, define only the procedures you need, because extra communication overhead may be avoided when the compiler detects that you do not care about certain events.

The arguments used in mouse procs generally follow one of these forms:

For Click(), DblClick(), MouseDown(), MouseUp(), MouseEntered(), MouseExited(), and MouseMove():
client/Click(object, location, control, params)
atom/Click(location, control, params)
For MouseDrag() and MouseDrop():
client/MouseDrag(src_object, over_object, src_location, over_location, src_control, over_control, params)
atom/MouseDrag(over_object, src_location, over_location, src_control, over_control, params)
For MouseWheel():
client/MouseWheel(object, delta_x, delta_y, location, control, params)
atom/MouseWheel(delta_x, delta_y, location, control, params)

The location argument varies with the type of control. For the map, it will be the turf where the mouse action happened. For info controls (statpanels), it will be the name of the statpanel where the action happened. For grid controls, it will be the cell where the action happened. For others controls it may vary, but most will leave this blank.

The control argument is the ID of the skin control where the action happened, such as "mappane.map" or "mainwindow.banner".

The params argument is text, and can be converted to a list using params2list(). It may contain any of the following properties, which will only be set if they are used:

The icon-x/y coordinates are integers, and try to point to the actual pixel in the icon before any atom transforms are done; i.e. if the icon were scaled up to 3 times its size using the transform var, then a 3×3 region of pixels would all have the same icon-x/y values. The lower left pixel of the icon is 1,1. The vis-x/y parameters are screen-based, and their origin (1,1) is wherever the lower left corner of the icon is rendered.

Note: vis-x/y will not be included in the parameters if they are the same as icon-x/y.

If the mouse is over an overlay, icon-x/y and vis-x/y are relative to the parent object, not the overlay icon itself, so it's possible to have value outside of the normal range of 1,1 to [width],[height].

The mouse pointer may be customized as well. The following variables all deal with the appearance of the pointer. They do not control what actions may be taken by the user, but they provide hints to the user about what actions may work.

When selecting a mouse pointer, you may provide your own custom icon or use one of the built-in pointers.

Note: Older games compiled prior to BYOND 4.0 had a different format for the MouseDown() and MouseUp() procs. These used icon_x and icon_y as arguments, but control and params have replaced them.

Note: Games compiled before version 514 did not have the button parameter, so they handled the left, middle, and right parameters differently. In old versions, only the button used in the action (left, middle, right) was included as a parameter; now all buttons being held or changed are included, and button is the mouse button that changed.


mouse pointers

See also:
mouse handling
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_drop_zone var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
mouse_pointer_icon var (client)

The following mouse pointers are built-in and may be assigned to any of the mouse pointer variables. Of course, you can also define your own custom mouse pointers using an icon file.

MOUSE_INACTIVE_POINTER (0)
MOUSE_ACTIVE_POINTER (1)
MOUSE_DRAG_POINTER
Same as mouse_drag_pointer = MOUSE_ACTIVE_POINTER.
MOUSE_DROP_POINTER
Same as mouse_drop_pointer = MOUSE_ACTIVE_POINTER.
MOUSE_ARROW_POINTER
Same as mouse_over_pointer = MOUSE_INACTIVE_POINTER.
MOUSE_CROSSHAIRS_POINTER
Same as mouse_over_pointer = MOUSE_ACTIVE_POINTER.
MOUSE_HAND_POINTER

null

Variables that are not initialized have the value null. This value is distinct from 0 and "". If you compare it to these, using the == operator, it is not equal. However, in a numeric context (like a mathematical operation), null evaluates to 0 and in a text context (like insertion into a text expression), null evaluates to "". In a logical expression, null, 0, and "" evaluate to false and all other values are true.

In an embedded text expression, null behaves like "". That means, if you are expecting a variable to display a 0, you should explicitly initialize it to 0 rather than leaving it as null.


preprocessor

The preprocessor performs various transformations on source code as the DM compiler reads the file. It may be used to define macros—that is words which are replaced by other fragments of code. It is also possible to insert other source code files and to conditionally compile or not compile sections of code.

Preprocessor commands are called directives. They are placed on a line by themselves and always begin with a hash symbol #. The preprocessor directives recognized by DM are the same as standard C compilers:

#define
#if
#elif
#ifdef
#ifndef
#else
#endif
#include
#pragma
#error
#warn

DM_BUILD macro

See also:
byond_build var (world)
byond_build var (client)
DM_VERSION macro
preprocessor

This macro indicates the minor version of the compiler, which is useful during BYOND beta testing. More often, you will want to use the DM_VERSION macro instead, which is the major version.


DM_VERSION macro

See also:
byond_version var (world)
byond_version var (client)
DM_BUILD macro
preprocessor

This macro indicates the version of the compiler. This could be useful when distributing code that uses new language features that would not compile in older compilers.

Example:

#if DM_VERSION < 230 #error This compiler is too far out of date! #endif

__FILE__ macro

See also:
ASSERT proc
DEBUG definition
__LINE__ macro
__MAIN__ macro
__PROC__ macro
__TYPE__ macro
__IMPLIED_TYPE__ macro

The __FILE__ macro expands to a string containing the name of the current source file. This may be useful when generating debugging error messages.


__IMPLIED_TYPE__ macro

See also:
__FILE__ macro
__LINE__ macro
__PROC__ macro
__TYPE__ macro
new proc
locate proc
istype proc

The __IMPLIED_TYPE__ macro is replaced by a reference to the type path implied at the current point in compilation. For instance, when using the new proc and assigning to a var, the type path for new() is implied by the var's type. Implied types are also automatically used in locate(), and are used by default for the second argument in istype().

Example:

proc/Factory(new_type) world.log << "Creating new [new_type]" return new new_type() proc/CreateThing() // pass /thing to Factory var/thing/T = Factory(__IMPLIED_TYPE__)

__IMPLIED_TYPE__ is valid in the following situations:

This is actually a pseudo-macro; the preprocessor doesn't handle it directly.


__LINE__ macro

See also:
ASSERT proc
DEBUG definition
__FILE__ macro
__PROC__ macro
__TYPE__ macro
__IMPLIED_TYPE__ macro

The __LINE__ macro is replaced by the line number in the current source file. This may be useful when generating debugging error messages.


__MAIN__ macro

See also:
preprocessor

The __MAIN__ macro is defined in the main .dme file being compiled. In all other files included by this file, __MAIN__ is not defined.

The purpose of this is for library writers to package a small demo of their library directly in the library source code. When users compile the library directly, the library's own .dme is the main file and can include extra files that are not normally part of the library.

Example:

#ifdef __MAIN__ #include "demo.dm" #include "demo.dmm" #endif

If the demo requires a lot of extra resources, it is probably better to package the demo as a separate project. Small demos, however, are nice and convenient using this "auto-demo" technique—especially since Dream Seeker automatically launches Dream Maker after installing a library containing a .dme file.


__PROC__ macro

See also:
__FILE__ macro
__LINE__ macro
__TYPE__ macro
__IMPLIED_TYPE__ macro

The __PROC__ macro is replaced by a reference to the current proc being compiled. This may be useful when generating debugging error messages, especially when wrapped in nameof, e.g. nameof(__PROC__).

This is actually a pseudo-macro; the preprocessor doesn't handle it directly.


__TYPE__ macro

See also:
__FILE__ macro
__LINE__ macro
__PROC__ macro
__IMPLIED_TYPE__ macro

The __TYPE__ macro is replaced by a reference to the type path currently being compiled. This may be useful when generating debugging error messages. If used in a global proc, the value will be null.

This is actually a pseudo-macro; the preprocessor doesn't handle it directly.


#define directive

See also:
preprocessor
Format:
#define Name Value
#define Name(Parameters) Value
Args:
Name: A macro definition.
Value: The value to substitute for Name.
Parameters: Arguments to pass into the macro.

The #define statement creates a macro that is substituted for Name. Substitution only applies to whole words. Text inside of double or single quotes is not processed for substitution, so "This is BIG." would not be modified even if a macro named BIG were defined. That is different from "This is [BIG].", where BIG is an embedded expression, which does get processed for macro substitution.

Example:

#define DAY 0 #define NIGHT 1 var/daytime = NIGHT //daytime = 1

Example:

#define SQR(X) ((X)*(X)) var/x = SQR(2) //x = ((2)*(2)) = 4

Note that it's usually important to use parentheses around any arguments you use in a macro. Otherwise strange results may occur if you use an expression such as 2+3. In the SQR(X) example, if there were no parentheses around each X then the expansion of the macro would be (2+3*2+3). Since the * operator has a higher precedence than + the result is 11, not 25 as expected. It's equally important to put parentheses around the entire macro for the same reason.

Variadic macros

The last parameter of a macro can end in ... which means that it and all other arguments following it count as a single argument. This is called a variadic macro because it lets you use a variable number of arguments. The last parameter will also become optional.

Example:

#define DEFAULT_LIST(n, items...) if(!n) n = list(items)

#var to string

In a macro's body, if you precede a parameter by #, the replacement value will be turned into a string. For instance, 2 would become "2".

Example:

#define DEBUG_VAR(v) world.log << "[#v] = [v]" DEBUG_VAR(usr.x) // world.log << "usr.x = [usr.x]"

##var concatenation

A parameter preceded by ## in the macro body is substituted directly, without any spaces. If you use this with the last argument in a variadic macro, any preceding spaces and a comma (if found) will be removed if the replacement is empty.

Example:

#define MACROVAR(k) var/macro_state_##k // MACROVAR(right) becomes var/macro_state_right #define PREFIX_LIST(x, y...) list(x, src, ##y) // PREFIX_LIST(1, 2, 3) becomes list(1, src, 2, 3) // PREFIX_LIST(4) becomes list(4, src)

n###var repeat

Using ### in the macro body, preceded by a number, will repeat the replacement a certain number of times.

Example:

#define SAYTWICE(t) 2###t #define TOTEXT(t) #t world << "[TOTEXT(SAYTWICE(hi))]" // world << "hihi"

DEBUG definition

See also:
#define directive
Format:
#define DEBUG

If DEBUG is defined, source file and line number information will be stored in the compiled .dmb file. If a proc crashes during execution and DEBUG information is present, the current source file name and line number will be indicated in the error output.

This option increases the size of the .dmb, typically by about 10%. Execution of the code may also be a tiny bit slower.

If you are distributing the .dmb to players and you do not want them to have debug access at runtime, you should not compile in debug mode.

If you want to use the run-time profiler (see the debugging options in Dream Seeker), you must compile in debug mode. Then you can get a report of CPU usage by your various procs.


FILE_DIR definition

See also:
cache
icons
Format:
#define FILE_DIR Path
Args:
Path: A search path on the current filesystem.

This macro defines a search path to be used in evaluating resource files (icons and sounds). First the current directory is searched, then the first FILE_DIR path, then the next, etc.

Example:

#define FILE_DIR icons #define FILE_DIR icons/mobs mob/clown icon = 'clown.dmi'

This searches for the file at the paths "./clown.dmi", "./icons/clown.dmi", and "./icons/sounds/clown.dmi", where "." is the directory of the current source file.


#elif directive

See:
#if directive

#else directive

See:
#if directive

#endif directive

See:
#if directive

#error directive

See also:
preprocessor
#warn directive
Format:
#error Text
Args:
Text: an error message to display

The #error directive halts compilation and displays the specified message.

Example:

#if DM_VERSION < 4 #error This compiler is too far out of date! #endif

#if directive

See also:
#define directive
#ifdef directive
Format:
#if Val
...
#elif Val2
...
#else
...
#endif
Args:
Val: A logical expression.

The #if statement is used to conditionally compile code. If Val is true (non-zero), the code following the #if statement will be compiled. Otherwise, compilation skips to the next #elif, #else, or #endif statement.

The function defined() can be used in the conditional expression. It is true if its argument is a defined macro (with #define) and false otherwise.

Example:

#if defined(DEBUG) // This code will be compiled if DEBUG is // defined #else // This code will be compiled if DEBUG is // not defined #endif

You can also use fexists() in a conditional to check if a file exists.


#ifdef directive

See also:
#define directive
#if directive
#ifndef directive
Format:
#ifdef Name
Args:
Name: A macro definition.

The #ifdef statement is used to conditionally compile code. It is equivalent to #if defined(Name).


#ifndef directive

See also:
#define directive
#if directive
#ifdef directive
preprocessor
Format:
#ifndef Name
Args:
Name: A macro definition.

The #ifndef statement is used to conditionally compile code. It is equivalent to #if !defined(Name).


#include directive

See also:
#define directive
#pragma directive
preprocessor
Format:
#include "Filename"
#include <Filename>
Args:
"Filename": The path to the filename to include, from the current directory.
<Filename>: The path inside the BYOND lib directory.

The #include statement causes the compiler to process another file before continuing in the current source file.

If a file is included multiple times, only the first occurrence will be processed. That is a convenient addition to the standard C preprocessor, which DM otherwise emulates quite closely. If you want the file to be included more than once, put the line #pragma multiple somewhere in the file.

The file <stddef.dm> is automatically included before all other source code. You can view the contents of that file by creating a file with that name in Dream Maker.

Example:

#include "test.dm" // checks ./test.dm #include <test.dm> // checks lib-path/test.dm

The BYOND lib directory is called "lib" and is located in the BYOND system directory (typically "\Program Files\Byond\lib"). If the file is not found there, it also looks in the user lib directory, which would typically be "...\Byond\user\login-name\lib".

Note that the compiler interface allows you to include files graphically by simply clicking the checkbox next to the file. This creates an include statement for you in the .dme project environment file. The only time you would still want to manually include files is when you need to ensure a certain order of processing. For example, if file "MyCode.dm" overrides procedure definitions of an object defined in "LibCode.dm", you should include "LibCode.dm" at the top of "MyCode.dm". Most other DM code is independent of order, but overriding procedure definitions is not. The compiler will warn you in such cases if you forget.

Another case in which you should manually include files is if you are writing a library to be used by other programmers. Since the .dme file is not distributed with a library, all necessary inclusions must be made in the .dm files.


#pragma directive

See also:
#define directive
#include directive
preprocessor

The #pragma directive alters the compiler's behavior in various ways.

#pragma multiple
Allows this file to be included more than once. Ordinarily the #include directive only allows a file to be included once.
#pragma ignore Warning
#pragma warn Warning
#pragma error Warning
Changes how the compiler handles certain warnings. They can be ignored, enabled, or elevated to errors. The ID of a warning is printed alongside the warning message. Multiple warnings can be separated by commas.
#pragma push
Save the current state of warnings, so a warning's level can be temporarily changed to ignore, warn, or error.
#pragma pop
Restore a previously saved warning state.

Example:

// temporarily ignore the unused_var warning #pragma push #pragma ignore unused_var proc/GNDN() var/nothing // var defined but not used #pragma pop

Pragmas will not be inherited by libraries included in your project.


#undef directive

See also:
#define directive
preprocessor
Format:
#undef Name
Args:
Name: A macro definition.

The #undef statement removes a macro definition.


#warn directive

See also:
preprocessor
#error directive
Format:
#warn Text
Args:
Text: a warning message to display

The #warn directive displays the specified message as a warning, but does not prevent the project from compiling.

Example:

#ifdef USE_LIGHTING #warn The lighting feature in MyLibrary is experimental. #endif

sounds

See also:
FILE_DIR definition
cache
sound proc
/sound datum
load_resource proc

A sound stored in a file may be referenced by putting single quotes around the filename. The file extension determines the type of sound. Currently supported music types include MIDI (.mid or .midi), and module formats .mod, .it, .s3m, .xm, and .oxm. Supported sound effect formats include .wav, .ogg, .mp3, .raw, .wma, and .aiff.

Example:

world << sound('fugue.midi')

This example plays the specified midi file to all players.


text

See also:
<< output operator
entities (text)
macros (text)
tags (text)
text proc
Unicode

Text consists of a string of characters enclosed in double quotes. To place a quote inside a string, escape it with a backslash \ character. You will also need to escape a backslash if you want to use one on purpose.

Example:

usr << "He said, \"Hi.\""

This example sends some text to the usr: He said, "Hi."

Backslashes are also used for special macros and to escape other characters that would normally be hard to include in a string. A backslash at the end of a line will ignore the line break, and continue the string on the next line after ignoring any leading spaces.

To insert a variable expression into a string, enclose it in brackets []. These are referred to as embedded text expressions. An object expression will display the object's name preceded by the text macro \the or \The if no other article has been specified. Capitalization of the article is inferred from context.

Example:

mob/verb/shout(T as text) world << "[usr]: [T]"

If this example is called by a mob named "Bill" with the text "hi everybody!", it will display "Bill: hi everybody!".

On the other hand, if it is called by a mob named "cat", it would display "The cat: hi everybody!".

Via operator overloading you can define an operator"" proc for an object to return different text when it's embedded in a string.

Document strings

For lengthy text strings, DM provides a special text document syntax. This begins with {" and ends with "}. It may include multiple lines and even un-escaped double quotes, but it still parses escape characters and embedded expressions.

Example:

mob/verb/end() usr << {" This is the way the world ends This is the way the world ends This is the way the world ends Not with a bang but a whimper. --T.S. Eliot "Hollow Men" "} del world //the end!

Raw strings

DM also has a format for raw strings, which do not allow escape characters or embedded expressions. This can be useful for many situations, especially regular expressions which tend to use characters that need escaping. There are three ways to specify a raw string. All of them begin with the @ character.

Simple raw strings follow @ with a single-character delimiter, usually " but it can be almost anything, and end when that delimiter is seen again. Line breaks are not allowed in simple raw strings.

Examples:

world << @"I can say \ or [] without escaping anything!" world << @#Here I can use "quotes" but not the pound sign.# var/regex/R = new(@/(\d+)/) // without raw strings world << "I can say \\ or \[] without escaping anything!" // lying world << "I have to escape \"quotes\" to use them." var/regex/R = new("(\\d+)")

Complex raw strings use more complicated delimiters, but they let you include line breaks. There are two ways to do this: One starts with @{" and ends with "}, so it looks like the familiar document string format. The other way starts with @(XYZ), where XYZ is any arbitrary text you want it to be, and ends when that same text is encountered.

With a complex raw string, a single leading and/or trailing line break will be ignored.

Examples:

world << @{" Now I have absolute freedom to use "quotes" or [brackets] or line breaks, as long as I don't follow a quote with a closing brace. "} world << @(~~~) Until three tilde (~) characters are seen, this is a valid string. ~~~ // end of string world << @(!!)You don't need a line break if you don't want one.!!

entities (text)

See also:
macros (text)
tags (text)
text

Special characters may be inserted into text using HTML syntax. Such characters are known as entities. They start with an ampersand and end with a semicolon. The main reason for doing this is to insert characters that otherwise have a special meaning. The most common entities have names. The rest must be referred to by their Unicode character number (e.g. &#38; is the same as &amp;). The common ones are listed in the following table. Note that the same effect may be achieved by simply escaping the special character (like \<). The full entity syntax is included for generality.

&amp; &
&lt; <
&gt; >
&quot; "
&copy; ©

macros (text)

See also:
icon text macro
text
text proc

Text macros start with '\' (a backslash) and end with a space or other punctuation.

\the, \The // insert 'the' (if needed) \a, \an, // insert 'a(n)' or 'some' (if needed) \A, \An \he, \He // insert 'he/she/they/it' \she, \She // same \his, \His // insert 'his/her/their/its' \him // insert 'him/her/them/it' \himself // insert 'himself/herself/themself/itself' \herself // same \hers // insert 'his/hers/theirs/its' \proper // used in an object name to force proper-noun behavior \improper // used in an object name to force improper-noun behavior \th // insert 1st, 2nd, 5th etc. \s // insert 's' if [] was plural \icon // insert icon of following [] \ref // insert a unique id for following [] \roman // insert following [] as a lower-case roman numeral \Roman // insert following [] as an upper-case roman numeral \... // suppress final new line \t // insert tab \n // insert new line \" // insert double quote \\ // insert backslash \< // insert &amp;lt; (less than) \> // insert &amp;gt; (greater than) \(space) // skip a space \(newline) // skip a newline (and following space) \xNN // insert a character by its ASCII/Unicode value \uNNNN // " \UNNNNNN // "

Example:

mob/verb/steal(M as mob,obj/O as obj in M) O.loc = usr view() << "[usr] finds \himself \an [O]."

Example:

var/DayCount proc/NewDay() DayCount++ world << "The [DayCount]\th day dawns."

Example:

obj/CPU name = "\improper CPU" //prevent capitalization from causing proper-noun behavior

icon text macro

See also:
icon_state var (atom)
macros (text)
style sheets
tags (text)

The \icon macro is used to treat the following embedded expression (in []'s) as an icon rather than as text. An object, for example, would be replaced by its icon rather than by its name.

Example:

usr << "You look like this: \icon[usr]!"

The \icon macro expands internally to the <IMG> tag. The above example, could be rewritten like this:

usr << "You look like this: \ <IMG CLASS=icon SRC=\ref[usr.icon] ICONSTATE='[usr.icon_state]'>!"

Note that the current icon state of the object is automatically used. Also note that the image belongs to a class called icon. That allows you to configure the way icons are displayed by using a style sheet. The following default style rule causes icons to be shrunk to 16 by 16 pixels so they fit in better with surrounding text:

IMG.icon {width: 16px; height: 16px}

You could override this setting globally in your own style sheet. You could even define rules to allow individual icons to be formatted differently from the rest.

Example:

BIG IMG.icon {width: 32px; height: 32px} SMALL IMG.icon {width: 16px; height: 16px}

With those rules in place, you could output a full sized icon by using the <BIG> tag:

usr << "You look like this: <BIG>\icon[usr]</BIG>!"

The one time that one might want to use the <IMG> tag directly is to specify the ALT text to be displayed on clients which don't support graphical icons.

Specific states, directions, and frames of an icon can be displayed in lieu of the default through use of the following tags:

Example:

usr << "You look like this: \ <IMG CLASS=icon SRC=\ref[usr.icon] ICONSTATE='glowing' ICONDIR=NORTH ICONFRAME=2>!"

Note that the \icon macro does not work in the mini-browser; it is only for text output. To make icons appear in an HTML document, use browse_rsc() to send an icon to the client before using browse() to display it.


ref text macro

See also:
Topic proc (client)
icon text macro
locate proc
macros (text)
tag var (datum)

The \ref text macro inserts a unique identification number or text string for the following embedded object (inside []'s).

In older versions of BYOND, if an object had a tag, that was used instead. However this has often proved to be problematic, so anything compiled from version 512 onward should expect to output a reference number. If you want to use the tag, which stands a better chance of still being valid if the object is deleted and recreated (like in a world reboot), you can output the object's tag explicitly.

The primary use for object references embedded in text is in topic links. This allows you to encode a reference to an object in the href value of a hyperlink. (Just make sure the object does not get deleted before the user executes the link. See garbage collection.)

Topic links that contain a parameter "src" assigned to an object reference are treated somewhat specially. Unless you override client.Topic() to do otherwise, the default behavior is to call the referenced object's own Topic() procedure.

Example:

mob/verb/test() usr << "Click <a href=?src=\ref[src];action=start>here</a>!" mob/Topic(href,href_list[]) switch(href_list["action"]) if("start") usr << "Starting the game..." else return ..()

The above example uses an embedded reference to the player's own mob to create a link to a topic handled by that mob's Topic() proc. The href_list parameter is simply the result of params2list(href).

In that example, the embedded reference was automatically converted back into an object (dereferenced) for you. If you embed references to additional objects in the href data, you would have to dereference those yourself using the locate() instruction.


style sheets

See also:
CSS attributes
entities (text)
macros (text)
script var (client)
tags (text)
text

HTML tags, such as <font> may be used to directly format output text. Another approach, however, is to use HTML tags to specify purely structural information and use a style sheet to define how various elements within that structure should be treated. DM uses a subset of the Cascading Style Sheet (CSS) language, which was introduced for this purpose in HTML documents.

This section discusses the syntax of style sheets as an independent element. For information on how to include the style sheets in your DM code, see the section on client.script.

As an example of a style sheet, one might want combat and conversational messages to appear differently—perhaps using different colors. Instead of using the <font> tag to color the text, you could use <span> to mark the beginning and ending of the text and to specify what kind of message it is. The result might be text such as the following:

"[usr] <span class=combat>spanks</span> [targ]!" "[usr] says, '<span class=chat>[msg]</span>'"

The class attribute may be used with any tag, but span and div are often convenient because they have no other side-effect but defining the style class. span is for text within a single paragraph and div is for whole paragraphs. The way text belonging to a particular class is formatted may be controlled in a style sheet such as the following:

.combat {color: red} .chat {color: green}

This says that text in the combat class should be colored red and text in the chat class should be colored green. These classes are not pre-defined; you can create whatever new style classes you need. (The color names are predefined however. You can find a list of them in HTML colors.

The advantage of using style sheets instead of direct formatting tags is that you can cleanly separate structural information (such as combat and conversational messages) from formatting information (such as red and green text). By separating the two, you or the player can easily plug in different formatting schemes without changing any of the actual content.

A style sheet is composed of a list of rules, such as the two rules in the preceding example. Each rule contains one or more selectors followed by a body of attribute assignments (in braces). The selector specifies the context of the rule and the body specifies the format.

A selector may specify a container tag (such as span, body, or p) and a class. The above example could have been written with a selector of span.chat. However, by leaving out the tag, it applies to any tag with class=chat. It is also possible to only specify the tag and not the class. In that case, the selector applies to any matching tag, regardless of class.

To specify a nested context, several simple selectors may be listed one after the other. For example, emphasized text within a combat message could be enlarged with the following rule:

.combat em {font-size: larger}

It is also possible to list several selectors separated by commas in order to make them all apply to the same body. For example, this next rule is equivalent to the two following ones:

.combat em, .chat em {font-size: larger} .combat em {font-size: larger} .chat em {font-size: larger}

The style rule body contains a list of attribute assignments, delimited by semicolons. Each assignment takes the form of an attribute name, followed by a colon, followed by the value of the attribute. The following table summarizes the recognized attributes and their possible values.

color #F00, #FF0000, red, rgb(255,0,0), rgb(100%,0%,0%)
background
font-size 10pt, 1.5em, 150%
font-style normal or italic
font-weight normal, bold, lighter, darker, or 100 to 900
font-family monospace, sans-serif, serif, cursive, ...
font style weight size family
text-decoration none, underline
text-align right, left, or center
vertical-align top, middle, bottom
text-indent 0.25in, 3em, 20pt
margin-left
margin-right
width 16px, 32px, auto
height
line-height 1.2

fonts

The font attribute is a special short-hand for assigning font-size, font-style, font-weight, and font-family in one statement. Any properties that are not specified in the font statement are assigned to their default values.

The font family may be a specific font name or a more general category such as monospace or sans-serif. Since not all users necessarily have the same fonts installed, it is a good idea to list alternate fonts. The desired font is placed first, followed by other possible fall-backs, each separated by a comma. Usually a general family such as monospace is listed last of all. Any font names containing a space should have quotes around them.

The following example sets the font for the <body> tag. Even if you don't explicitly use <body> in output text, it is applied implicitly.

body {font: 12pt 'Times New Roman', sans-serif}

This sets the font to 12 point and selects Times New Roman if it is available and otherwise falls back on a system-determined sans-serif font. This command also implicitly specifies not to use italics and to use a normal font weight (not bold).

Font sizes may be specified in points (1pt = 1/72 of an inch), picas (1pc = 12pt), pixels (px), inches (in), centimeters (cm), and millimeters (mm). There are also various levels corresponding to the old 1 to 7 HTML scale. These are xx-small, x-small, small, medium, large, x-large, and xx-large. In addition to these absolute font sizes, it is possible to use a relative size, such as 150% or equivalently 1.5em (1em = 100% of the current font size). This scales the font relative to the currently active font setting.

In addition to regular classes, there are special pseudo-classes for handling embedded hyperlinks. These are specified in the selector with the class starting with a colon rather than a dot. They are :link, :visited, and :active. These only apply to the <a> tag. The :link class applies to hyperlinks in their normal state. Once a link has been clicked, it belongs instead to the :visited class. When the user holds the mouse over a link, it temporarily belongs to the :active class. The only attribute that may change in an active or visited link is the text color.

margins and indents

Paragraphs can be given different margins according to your preferences. The margin-left attribute controls the left margin, and margin-right is the right margin. You can use specific sizes like inches or points, or a relative size unit like em or ex. (A percentage is interpreted so that 100% is 1em, not the width of the window.) Using the text-indent attribute will indent the first line of a paragraph from the left margin. It is possible to create a hanging indent by using a negative value for text-indent, like so:

body {text-indent: -0.5in; margin-left: 0.5in}

background colors

The background attribute is only relevant to the body context. It causes the entire terminal background to change color. When doing this, it is usually necessary to change the foreground colors of text or it may become unreadable. The various standard classes of output generated by DreamSeeker are in the following table.

system colors

system notice general notices from the client
system command echo command echoing
system command expansion command-line expansion list
system pager pager messages
system irc IRC command prefix

The value of the CLASS attribute may contain a list of classes separated by spaces. This permits client output to be in the 'system' class as well as more specific ones. That allows you to change all of these colors in one shot if you are too lazy to change them each individually. For example, if you define a style sheet that changes the background color, you might need to redefine the various foreground colors like this:

body {background: aqua; color: black} .system {color: red; font-weight: bold} .command {color: green}

In this example, the background color of the terminal will be aqua, normal text from the server will be black, and all output from the client will be bold and red, except echoed commands and expansion lists, which will be bold and green. The more specific .command rule is placed after the general .system rule so that its color takes precedence. This is how style sheets are composed—you write general rules first followed by any exceptions.

style rule precedence

The order in which rules are specified is one of the factors that determines precedence of style sheet commands. The language is known as Cascading Style Sheets because of its ability to handle several layers of stylistic rules, intermingling the configurations of the user and the designer in an ordered fashion.

Rules are selected by first finding all matching candidates for a given attribute in the current HTML tag being processed. If there is more than one, rules from a higher level style sheet take precedence over lower level ones. That means the basic user configurable settings in DreamSeeker are the lowest priority, followed by a style sheet in the user's .dms script file, followed by a style sheet from the designer's client.script setting, because that is the order in which these are read by the style sheet manager.

Rules from the same style sheet are ordered by specificity. The selector span.chat is more specific than .chat and .chat em is more specific than em. In general, the more classes referenced by a selector, the more specific it is. When that results in a tie, the selector with the greater number of tags takes precedence.

If two rules about the same attribute come from the same sheet and have the same specificity, the final one to be defined takes precedence.

In the rare event that a rule needs to break out of the normal order of precedence, it can be flagged as important. In this case it will take precedence over all other "unimportant" rules. However, if more than one rule is important, the normal rules of precedence will be used to resolve the conflict.

The important flag is applied after the attribute assignment like this:

body {background: white ! important; font: serif}

In the above example, only the background color is important, not the font specification.

style attribute

Style commands may also be inserted directly in an html tag to control its appearance. This does not have the advantages of style sheets, which separate content from presentation, but it does allow you to use the style sheet syntax when formatting text.

The following example uses the style attribute to color some text:

usr << "That <span style='color: red'>HURT</span>!"

As you can see, the style attribute of any tag can be assigned to a text string containing a list of attribute assignments. Just the body of the style rule is given, since no selector is needed to match the current context.

Maptext options

The atom.maptext var supports some additional CSS attributes.

vertical-align top, middle, bottom
text-shadow x-offset y-offset blur color
-dm-text-outlinewidth color style

Additionally, you can use the :hover pseudo-class to change the color of a link. As with other link pseudo-classes, only the text color can currently be changed.


tags (text)

See also:
entities (text)
macros (text)
style sheets
text

Text tags (also known as elements by snooty HTML purists) control how the text is formatted. HTML syntax is used, so all tags start with < and end with >. The tags which are currently supported by Dream Seeker, are listed below:

<A></A>              // anchor (hyperlink)
<ACRONYM></ACRONYM>  // acronym or abbreviation
<B></B>              // bold text
<BIG></BIG>          // one size bigger text
<BODY></BODY>        // body of html document
<BR>                 // line break
<CITE></CITE>        // citation reference
<CODE></CODE>        // program source code
<DFN></DFN>          // definition
<DIV></DIV>          // used in conjunction with style sheets
<EM></EM>            // emphasized text
<FONT></FONT>        // font face, color, and size
<H1></H1>            // heading level
<H2></H2>
<H3></H3>
<H4></H4>
<H5></H5>
<H6></H6>
<HEAD></HEAD>        // document head section
<HTML></HTML>        // html document
<I></I>              // italic text
<IMG></IMG>          // display icons
<KBD></KBD>          // keyboard input
<P></P>              // paragraph
<PRE></PRE>          // pre-formatted text
<S></S>              // overstrike text
<SAMP></SAMP>        // sample output
<SMALL></SMALL>      // one size smaller text
<SPAN></SPAN>        // used in conjunction with style sheets
<STRONG></STRONG>    // strongly emphasized text
<STYLE></STYLE>      // contains a style sheet
<TITLE></TITLE>      // document title
<TT></TT>            // typewriter style
<U></U>              // underline
<VAR></VAR>          // variable name
<XMP></XMP>          // preformatted (tags ignored)

In addition to these, the <BEEP> tag, which is not standard HTML, may be used to beep the terminal.

Some tags take additional parameters, known as attributes. The most common ones are <FONT> and <A>. The syntax for these is illustrated by the following two examples:

"How about <FONT FACE=Arial COLOR=red SIZE=+1>this</FONT>!" "Click <A HREF=byond.com TITLE=BYOND!>here</A>!"

As many attributes may be specified as desired. The attribute value may have quotes around it, but this is only necessary if the value contains spaces. It is usually more convenient to use single quotes so you don't have to escape the double quotes, but you can also embed the HTML in a text document to avoid the need for escaping quotes.

When applying color to text, you can use hexadecimal RGB or you can use one of the named HTML colors.

Text sizes range from 1 to 7, 1 being the smallest and 7 being the largest. In addition to absolute sizes, relative sizes may be specified (like +1 for one size bigger or -1 for one size smaller).


vars list var (global)

See also:
vars list var (datum)

This is a list of all global variables. The items in the list are the variable names. If the variable name is used as an index into the list, the value of that variable is accessed.

Example:

mob/verb/dumpglobal() for(var/V in global.vars) usr << "[V] = [global.vars[V]]"

This example displays all global variables. The global keyword is used here to distinguish it from src.vars, which in this example would be the mob's vars.


area

See also:
atom
procs (area)
rooms
vars (area)

Areas are derived from /area, which derives from /atom. Regions on the map may be assigned to an area by painting it onto the map. Areas off the map serve as rooms that objects may enter and exit.

For each area type defined, one area object is created at runtime. So for areas on the map, all squares with the same area type belong to the same instance of the area.

Additional instances of rooms may be created from the same type by explicitly creating them with null as the initial location. That is, the first argument to new() should either be null or left unspecified.

The following example defines the area prototype /area/outside. It also defines an action to be taken when somebody enters an area, namely to display its description.

Example:

area Entered(O) if(desc) O << desc return ..() outside desc = "Ah! A breath of fresh air!"

procs (area)

Built-in area procs:

area/proc
Click
Cross proc
Crossed proc
DblClick
Del
Enter
Entered
Exit
Exited
MouseDown
MouseDrag
MouseDrop
MouseEntered
MouseExited
MouseMove
MouseUp
MouseWheel
New
Read
Stat
Topic
Uncross proc
Uncrossed proc
Write

rooms

Areas that are not located on the map are referred to as rooms. When a player enters one, the map goes away and you have something like a text MUD. By default, there would be no way for players to move from one room to another, so you have to handle movement yourself.

You can check the variable area.x to see if a given area is on the map or not.

The following example puts players in a room when they log in and provides a single exit.

Example:

mob/Login() if(!loc) Move(locate(/area/birthing_hut)) return ..() area/birthing_hut Entered(O) O << "Waaaaah! You land in a pile of straw." return ..() verb/exit() if(Move(locate(1,1,1))) //jump to the map or whatever usr << "You crawl into the open air..." else usr << "The hut door is blocked. You cannot get out."

vars (area)

Built-in area vars:

area/var
alpha
appearance
appearance_flags
blend_mode
color
contents
density
desc
dir
filters
gender
icon
icon_state
invisibility
underlays
overlays
layer
luminosity
maptext
maptext_width
maptext_height
maptext_x
maptext_y
mouse_over_pointer
mouse_drag_pointer
mouse_drop_pointer
mouse_drop_zone var
mouse_opacity var
name
opacity
parent_type
plane
render_source
render_target
suffix
tag
text
transform
type
vars
verbs

parent_type var (area)

See also:
parent_type var

The default parent_type of /area is /atom.


atom

See also:
area
datum
mob
movable atoms
obj
procs (atom)
turf
vars (atom)

The /atom object type is the ancestor of all mappable objects in the game. The types /area, /turf, /obj, and /mob are all derived from /atom. You should not create instances of /atom directly but should use /area, /turf, /obj, and /mob for actual objects. The /atom object type exists for the purpose of defining variables or procedures that are shared by all of the other "physical" objects. These are also the only objects for which verbs may be accessible to the user.

/atom is derived from /datum, so it inherits the basic properties that are shared by all DM objects.


movable atoms

See also:
atom
mob
obj
procs (movable atoms)
vars (movable atoms)

The /atom/movable object type is the ancestor of all mappable objects that are capable of motion. The types /obj and /mob are derived from /atom/movable. You should not create instances of /atom/movable but should use /obj and /mob for actual objects. This object definition exists solely to define variables and procedures related to motion.


procs (movable atoms)

Built-in movement procs:

atom/movable/proc
Bump
Move

Bump proc (movable atom)

See also:
Move proc (movable atom)
Pixel movement
Format:
Bump(atom/Obstacle)
When:
Called when a movement fails due to a dense blockage.
Args:
Obstacle: The blocking object.
Default action:
If the obstacle is a mob and src is in its group, swap their positions. This is only done if the mobs both move by full tiles and do not use pixel movement, to preserve the behavior of older games.

Cross proc (atom)

See also:
Enter proc (atom)
Entered proc (atom)
Exit proc (atom)
Exited proc (atom)
Crossed proc (atom)
Uncross proc (atom)
Uncrossed proc (atom)
Move proc (movable atom)
group var (mob)
movement_mode var (world)
Pixel movement
Format:
Cross(atom/movable/O)
Returns:
1 to permit; 0 to deny.
When:
Called when another object attempts to overlap this one.
Args:
O: the object attempting to overlap.
Default action:
Allow overlap unless both atoms are dense. If both atoms are mobs, the behavior depends partly on whether they are in the same group.

The following behavior only applies to LEGACY_MOVEMENT_MODE. In other movement modes, src.Cross(O) returns 0 by default if src and O are both mobs in the same group.

If src completely covers the turf it is standing on, Cross() is called as part of turf.Enter(). This is to preserve the behavior of older games, which expect turf.Enter() to care about its contents.

If src and O are both mobs, and O is in src's group, overlap is allowed unless neither of them use pixel movement. Older games that do not use pixel movement expect that Bump() will be called, and by default Bump() will swap the mobs' positions. Swapping obviously only works in situations where a mob takes up a whole tile and only moves by tiles; for all other situations, allowing an overlap makes more sense.


Crossed proc (atom)

See also:
Enter proc (atom)
Entered proc (atom)
Exit proc (atom)
Exited proc (atom)
Cross proc (atom)
Uncross proc (atom)
Uncrossed proc (atom)
Move proc (movable atom)
group var (mob)
Pixel movement
Format:
Crossed(atom/movable/O)
When:
Called when an object has overlapped this one through Move(). Directly setting the object's loc or step_x/y vars does not result in a call to Crossed() or any other movement side-effects. The same goes for creation or deletion of an object at a location.
Args:
O: the object that moved and is now overlapping.
Default action:
none

Example:

obj/landmine Crossed(O) O << "You stepped on a land mine!" Explode()

Move proc (movable atom)

See also:
Bump proc (movable atom)
Enter proc (atom)
Entered proc (atom)
Exit proc (atom)
Exited proc (atom)
Cross proc (atom)
Crossed proc (atom)
Uncross proc (atom)
Uncrossed proc (atom)
loc var (atom)
locs list var (movable atom)
walk proc
Gliding
Pixel movement
Format:
Move(NewLoc,Dir=0,step_x=0,step_y=0)
Returns:
Success (jump): 1
Success (slide): Number of pixels moved
Failure: 0
When:
Called to move the object. By default, client.Move() calls this proc when players use direction keys. The automated movement functions (like walk()) also call this proc. Directly setting the loc variable does not call this procedure.
Args:
NewLoc: The new location.
Dir: The direction of movement (or 0).
step_x: The new step_x value, relative to NewLoc
step_y: The new step_y value, relative to NewLoc

Any Move() is either a slide or a jump. Normal walking around is a slide; it can be stopped partway. A jump is pass/fail. See more information below.

This is what happens by default:

  1. oldloc.Exit(src) is called for any turfs or areas being vacated, or the container if moving out of an obj or mob. neighbor.Uncross(src) is called for any atoms that will no longer be overlapping this object. If any of these return 0 (failure), movement fails.

  2. newloc.Enter(src) is called for any turfs or areas that may be entered for the first time, or the container if moving into an obj or mob. neighbor.Cross(src) is called for any atoms that may be in collision with this object if the move fully succeeds. If any of these return 0 (failure), then a slide can be cut short but a jump will fail completely.

  3. If any obstacles were encountered via Enter() or Cross() failing, then src.Bump(obstacle) will be called for each of them.

  4. If movement did not fail completely, then loc and step_x/y, will be changed, and the following calls will be made: oldloc.Exited() for any turfs, areas, or other containers vacated; neighbor.Uncrossed() for any movable atoms no longer overlapping; newloc.Entered() for any turfs, areas, or other containers being entered for the first time; and neighbor.Crossed() for any movable atoms now overlapping the object.

A movement is considered a slide if src is moving from one turf to another on the same z level, and the total pixel distance is less than either src.step_size or a full tile size (whichever is largest). Any other movement is a jump. Movement to the same turf with no step_x/y change is also considered a jump.


Uncross proc (atom)

See also:
Enter proc (atom)
Entered proc (atom)
Exit proc (atom)
Exited proc (atom)
Cross proc (atom)
Crossed proc (atom)
Uncrossed proc (atom)
Move proc (movable atom)
group var (mob)
Pixel movement
Format:
Uncross(atom/movable/O)
Returns:
1 to permit; 0 to deny.
When:
Called when another object attempts to stop overlapping this one.
Args:
O: the object attempting to get away.
Default action:
Allow the object to get away (returning 1)

Uncrossed proc (atom)

See also:
Enter proc (atom)
Entered proc (atom)
Exit proc (atom)
Exited proc (atom)
Cross proc (atom)
Crossed proc (atom)
Uncross proc (atom)
Move proc (movable atom)
group var (mob)
Pixel movement
Format:
Uncrossed(atom/movable/O)
When:
Called when an object has stopped overlapping this one through a call to Move(). Directly setting the object's loc or step_x/y vars does not result in a call to Uncrossed() or any other movement side-effects. The same goes for deletion of an object.
Args:
O: the object that moved and is no longer overlapping.
Default action:
none

Example:

obj/pressure_plate Uncrossed(O) // if no other mobs are standing on it... if(!(locate(/mob) in bounds())) // do something Release()

vars (movable atoms)

Built-in movement vars:

atom/movable/var
animate_movement
bound_x
bound_y
bound_width
bound_height
locs
screen_loc
glide_size
particles
step_size
step_x
step_y

animate_movement var (movable atoms)

See also:
Move proc (movable atom)
glide_size var (movable atoms)
Gliding
Default value:
FORWARD_STEPS (1)
Possible values:
NO_STEPS (0)
FORWARD_STEPS (1)
SLIDE_STEPS (2)
SYNC_STEPS (3)

Setting this to 0 causes movement between two adjacent positions to be displayed as a single discrete jump. Otherwise, objects will be made to glide from one position to another, using the movement animation defined in the icon file if one is defined.

By default, movement animation avoids cutting corners, since this can look very bad in some games. If you want objects to take the shortest (and smoothest) visual path when moving around, use SLIDE_STEPS instead of the default FORWARD_STEPS. This also allows the object to be facing in a different direction than it is moving, so make sure this is what you want.

SYNC_STEPS is intended for objects that move in unison as part of a larger "conglomerate" object. You should set the movement animation to SYNC_STEPS on all but a single "head" object, which will serve as the leader when choosing pixel step sizes. If you do not use SYNC_STEPS, there are cases where the pixel offsets of objects may get out of sync during motion, causing the object to visually break up. Because of the advent of features like big icons, this value is no longer of much use.

Note: This setting has no impact when used with pixel movement, except in special cases. See Gliding for more details.


bound_x var (movable atom)

See also:
bound_y var (movable atom)
bound_width var (movable atom)
bound_height var (movable atom)
step_x var (movable atom)
step_y var (movable atom)
locs list var (movable atom)
Pixel movement
Default value:
0

This var defines the left side of the physical atom's bounding box, in pixels. By default all atoms are assumed to be one tile in physical size.

The left edge of the bounding box starts bound_x pixels inward from the left edge of the atom's icon (as affected by step_x). A bound_x value of 4 means the atom has 4 pixels of empty space to its left.

Example: A 16×16 smiley face centered in a 32×32 icon should have a bound_x value of 8, since there are 8 pixels of empty space to the left.


bound_y var (movable atom)

See also:
bound_x var (movable atom)
bound_width var (movable atom)
bound_height var (movable atom)
step_x var (movable atom)
step_y var (movable atom)
locs list var (movable atom)
Pixel movement
Default value:
0

This var defines the bottom side of the physical atom's bounding box, in pixels. By default all atoms are assumed to be one tile in physical size.

The bottom edge of the bounding box starts bound_y pixels inward from the bottom edge of the atom's icon (as affected by step_y). A bound_y value of 4 means the atom has 4 pixels of empty space below it.

Example: A 16×16 smiley face centered in a 32×32 icon should have a bound_y value of 8, since there are 8 pixels of empty space below.


bound_width var (movable atom)

See also:
bound_x var (movable atom)
bound_y var (movable atom)
bound_height var (movable atom)
step_x var (movable atom)
step_y var (movable atom)
locs list var (movable atom)
icon_size var (world)
Pixel movement
Default value:
32 (width of default icon; depends on world.icon_size)

This var defines the width of the physical atom's bounding box, in pixels. By default all atoms are assumed to be one tile in physical size.

Example: A 16×16 smiley face centered in a 32×32 icon should have a bound_width value of 16.


bound_height var (movable atom)

See also:
bound_x var (movable atom)
bound_y var (movable atom)
bound_width var (movable atom)
step_x var (movable atom)
step_y var (movable atom)
locs list var (movable atom)
icon_size var (world)
map_format var (world)
Pixel movement
Default value:
32 (depends on world.icon_size)

This var defines the height of the physical atom's bounding box, in pixels. By default all atoms are assumed to be one tile in physical size.

Example: A 16×16 smiley face centered in a 32×32 icon should have a bound_height value of 16.

The default value depends on world.icon_size and world.map_format. In a topdown or tiled map_format, the icon height specified in world.icon_size is used. In other modes, height is irrelevant and tile "footprints" are square, so the icon width is used.


glide_size var (movable atoms)

See also:
animate_movement var (movable atoms)
glide_size var (client)
pixel_x var (atom)
pixel_y var (atom)
icon_size var (world)
movement_mode var (world)
fps var (client)
Gliding
Default value:
0

Note: The way this setting is used depends on world.movement_mode. See Gliding for more details.

This controls the number of pixels an object is moved in each footstep during animated movement. The default value of 0 chooses automated control over this value, which generally results in a minimum footstep of 4 pixels that is increased when necessary to keep up with motion on the turf grid.

Decimal values are allowed.

Be careful about using small glide sizes. Icons with high contrast pixel-level detail can look pretty ugly when displaced by short distances.

The glide size is measured in server ticks. If you use a different client tick rate by altering client.fps or client.tick_lag, the actual glide used will be scaled appropriately. E.g., if your client.fps is 4 times greater than world.fps, the actual glide amount each client tick will be glide_size/4.

This was renamed from pixel_step_size.


locs list var (movable atom)

See also:
bound_x var (movable atom)
bound_y var (movable atom)
bound_width var (movable atom)
bound_height var (movable atom)
step_x var (movable atom)
step_y var (movable atom)
loc var (atom)
contents list var (atom)
Default value:
list(src.loc)

This read-only var tells which turfs are being physically covered by the atom's bounding box. The purpose of this is for cases where you set the atom's bounds to change its physical size so that it ends up covering more than one turf.

This is different from the loc var in that every atom still has only one "true" location. A movable atom may cover multiple turfs, but only one turf is its loc. The loc var can be thought of as an anchor point, while the actual physical footprint is in locs.

For every turf in locs, this atom will also be in that turf's contents list.

If loc is not a turf, it will be the only item in the locs list. If loc is null, locs will be empty.


particles var (movable atom)

See also:
Particle effects
Default value:
null

A datum (not derived from /atom) containing information about a particle set attached to this atom. See Particle effects for more information.

Resetting this var to null after it has contained a particle set will cause any existing particles on this object to immiediately disappear.


pixel_step_size var (movable atoms)

Renamed to glide_size.


screen_loc var (movable atoms)

See also:
HUD / screen objects
layer var (atom)
screen var (client)
view var (client)
map_format var (world)

This is a text string that controls where an object that is listed in client.screen will appear on the user's screen. The format is:

"x,y" "x:px,y:py" "x1,y1 to x2,y2"

The bottom left corner of the map viewport (southwest) is "1,1". If the view is 11x11, then the top-right corner (northeast) is "11,11". (Changing world.map_format may change the range for screen_loc.)

A range of coordinates (the second format above) causes a square region to be filled with the object at each position. The southwest and northeast corners of the box are indicated in the screen_loc value.

Special keywords

The edges of the map may also be referenced by using directions, such as "3,NORTH". For convenience, the order of coordinates is arbitrary when using directions, so one may specify y before x as in "NORTH,WEST". In expressions such as the latter, you may also leave out the comma. Icon size is not taken into account, so a big icon with a screen_loc of "SOUTHEAST" will extend further to the right and may create a border (see "Outside the map" below).

The CENTER keyword can also be used. This can be used alone to completely center the object, or as either the x or y component. If the map covers an even number of tiles in either direction, pixel offsets will be applied automatically. Centering is relative to the regular map edges, and it does not take the icon's size into account.

The LEFT, RIGHT, TOP, and BOTTOM keywords (also TOPLEFT, TOPRIGHT, BOTTOMLEFT, BOTTOMRIGHT) can be used to anchor a screen object to the edge of the map control if the map is zoomed in so that some pixels are cut off. When you use these edge-alignment keywords, the icon size is taken into account, and the alignment of the icon changes to fit whichever edge you use. Because these keywords do not conform to the normal tile-based structure of the HUD, they can't be used for a range of tiles with the "to" format.

Note: Letterboxing, the blank space to either side of the map if it doesn't take up the whole map control, is not considered usable space. HUD objects aligned to the control edge appear inside any letterboxing, not on top of it.

Outside the map

In addition to objects inside of the map view, one may create border objects. Borders are automatically created when screen objects are placed at coordinates outside of the inner map view. For example, objects placed at y=0 fall on a border directly below the map and y=-1 is one tile below that. (The CENTER keyword is based on normal viewport bounds and not any extra borders.)

A big icon placed towards the northeast end of the map, if it spills over the edge, will create a border big enough for the whole icon to be shown. You can avoid this by using the TILE_BOUND appearance flag. Transforms on this atom are not taken into account when determining whether to add a border.

Offsets

Offsets may be applied to screen_loc coordinates. For example, "NORTH+1,WEST" is in a border above the map. "CENTER+2,CENTER-1" will appear 2 units right, 1 unit down from the center of the map.

Non-integer offsets like 1.5 are allowed; the fractional part will be counted towards a pixel offset.

Offsets may be specified in percentages as well. These effectively always count as pixel offsets and will never be used to determine if a border should be added. "WEST+100%" and "100%" are basically identical to "EAST" in most respects, and "WEST+50%" is basically the same as "CENTER". If you're using the edge keywords (LEFT, TOP, etc.), this percentage is relative to the control edge and also factors in the icon size, so "LEFT+100%" is equivalent to "RIGHT".

It is also possible to specify a pixel offset. Screen objects do not use pixel_x and pixel_y for this purpose, because it is intended that an object could exist on the map and in the screen object list simultaneously, so positioning must be independent. Pixel offsets are specified after a colon like this: "1:16,1:16". In this case the object is shifted to the northeast by 16 pixels.

Layering

Screen objects on a plane will appear above non-screen objects on the same plane regardless of layer, except that BACKGROUND_LAYER or EFFECTS_LAYER may be used to move the objects forward or back.

Secondary map controls

You can use HUD objects in any additional map controls that might appear in game's skin file. If you have a second map named map2 for instance, then you can use "map2:1,1" or something similar as a screen_loc. If the map control is set to automatically scale to fit its contents, it will try to show every object you put there.

Note: For secondary-map HUD items, you should not use the full window.control ID, just the id of the control itself. Map controls should always have a unique id.


step_size var (movable atom)

See also:
step_x var (movable atom)
step_y var (movable atom)
Move proc (movable atom)
locs list var (movable atom)
fps var (world)
icon_size var (world)
Gliding
Pixel movement
Default value:
32 (width of default icon; depends on world.icon_size)

This var defines how fast, in pixels, an atom will move by default. If you use lower values of step_size for most items in your world, you may want to consider raising world.fps (at higher performance cost).

When Move() is called by a step or walk, or by the built-in client movement verbs, a change of step_size is applied to step_x and/or step_y. Any movement within the speed of step_size, or up to one tile in distance (whichever is greater), is considered a slide and may partially succeed if an obstacle is bumped before reaching the final position.


step_x var (movable atom)

See also:
step_y var (movable atom)
step_size var (movable atom)
bound_x var (movable atom)
Move proc (movable atom)
locs list var (movable atom)
Pixel movement
Default value:
0

This var defines the position of the atom (in pixels) relative to its tile, on the x axis. A step_x of 5 means the atom actually is shown 5 pixels east of the tile's western edge.

The atom's actual bounding box may not begin at step_x, but can be set even further in via bound_x.

Example: A 16×16 smiley face centered in a 32×32 icon should have the following bounds:

For the smiley to appear at the left edge of the tile it is standing on, it would need a step_x value of -8. A step_x value of 8 takes it all the way to the rightmost edge of the tile. Anything outside of the range -8 to 8 will have the atom straddling multiple turfs.


step_y var (movable atom)

See also:
step_x var (movable atom)
step_size var (movable atom)
bound_y var (movable atom)
Move proc (movable atom)
locs list var (movable atom)
Pixel movement
Default value:
0

This var defines the position of the atom (in pixels) relative to its tile, on the y axis. A step_y of 5 means the atom actually is shown 5 pixels north of the tile's southern edge.

The atom's actual bounding box may not begin at step_y, but can be set even further in via bound_y.

Example: A 16×16 smiley face centered in a 32×32 icon should have the following bounds:

For the smiley to appear at the bottom edge of the tile it is standing on, it would need a step_y value of -8. A step_y value of 8 takes it all the way to the top edge of the tile. Anything outside of the range -8 to 8 will have the atom straddling multiple turfs.


procs (atom)

Built-in atom procs:

atom/proc
Click
Cross proc
Crossed proc
DblClick
Del
Enter
Entered
Exit
Exited
MouseDown
MouseDrag
MouseDrop
MouseEntered
MouseExited
MouseMove
MouseUp
MouseWheel
New
Read
Stat
Topic
Uncross proc
Uncrossed proc
Write

Click proc (atom)

See also:
Click proc (client)
DblClick proc (atom)
MouseDown proc (atom)
MouseDrag proc (atom)
MouseDrop proc (atom)
MouseEntered proc (atom)
MouseExited proc (atom)
MouseMove proc (atom)
MouseUp proc (atom)
MouseWheel proc (atom)
show_popup_menus var (client)
Format:
Click(location,control,params)
When:
Called when the object is clicked.
Args:
location: the turf, stat panel, grid cell, etc. in which the object was clicked
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This proc is called by the default client.Click() procedure.

The following example allows the player to walk to a position by clicking it.

Example:

turf/Click() walk_to(usr,src)

DblClick proc (atom)

See also:
Click proc (atom)
DblClick proc (client)
MouseDown proc (atom)
MouseDrag proc (atom)
MouseDrop proc (atom)
MouseEntered proc (atom)
MouseExited proc (atom)
MouseMove proc (atom)
MouseUp proc (atom)
MouseWheel proc (atom)
show_popup_menus var (client)
Format:
DblClick(location,control,params)
When:
Called when the object is double-clicked.
Args:
location: the turf, stat panel, grid cell, etc. in which the object was double-clicked
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This proc is called by the default client.DblClick() procedure.

This example allows the player to teleport to a position by double clicking it.

Example:

turf/DblClick() usr.Move(src)

Enter proc (atom)

See also:
Entered proc (atom)
Exit proc (atom)
Exited proc (atom)
Cross proc (atom)
Crossed proc (atom)
Uncross proc (atom)
Uncrossed proc (atom)
Move proc (movable atom)
movement_mode var (world)
Pixel movement
Format:
Enter(atom/movable/O, atom/oldloc)
Returns:
1 to permit; 0 to deny.
When:
Called when an object attempts to enter the contents list.
Args:
O: the object attempting to enter.
oldloc: the old (current) loc of the object attempting to enter.
Default action:
Explained below.

Areas, objs, and mobs will always permit anything to enter by default.

The following behavior only applies to LEGACY_MOVEMENT_MODE. In all other movement modes, the turf's contents are not taken into account. Only the result of turf.Cross() matters.

Turfs will return 1 (permit) or 0 (deny) based on density. In simple terms, if the atom that is entering is dense, then the turf will deny entry if the turf itself or its contents (any that take up the full tile) are dense.

What actually happens in turf.Enter() is more detailed: Cross() is called for the turf, and if it succeeds (movement is permitted), then Cross() is called for any atoms in turf.contents that cover the entire tile. If any Cross() call fails, Enter() fails too and will return 0.

If a mob is standing on a turf but its bounding box does not cover the whole tile, it is ignored by Enter(). Instead, its Cross() proc is called if there is a danger of the object overlapping it.


Entered proc (atom)

See also:
Enter proc (atom)
Exit proc (atom)
Exited proc (atom)
Cross proc (atom)
Crossed proc (atom)
Uncross proc (atom)
Uncrossed proc (atom)
Move proc (movable atom)
step_x var (movable atom)
step_y var (movable atom)
Format:
Entered(atom/movable/Obj,atom/OldLoc)
When:
Called when an object has entered the contents list through Move(). Directly setting the object's loc or step_x/y vars does not result in a call to Entered() or any other movement side-effects. The same goes for creation or deletion of an object at a location.
Args:
Obj: the object that entered (a mob or obj).
OldLoc: the previous location of the object.
Default action:
None for most atoms, but turfs will call Crossed().

Example:

turf/pit Entered(O) O << "OUCH. You fell in a pit!"

The mob's Entered() and Exited() procs can be used to control what happens when objects are added or removed from the mob's inventory. Of course that could all be done within get() and drop() verbs, but the following code separates user interface from lower-level functions.

Example:

obj var weight = 10 verb get() set src in oview(1) if(Move(usr)) usr << "You pick up \a [src]." else usr << "You cannot pick up [src]." drop() set src in usr if(Move(usr.loc)) usr << "You drop \a [src]." mob var weight max_weight = 50 Entered(obj/O) weight += O.weight Exited(obj/O) weight -= O.weight Enter(obj/O) //only allow entrance if weight is within the limit if(O.weight + weight <= max_weight) return ..()

To see the advantages of this arrangement, imagine that there are certain situations in which an object may be created directly within the mob's inventory without the mob picking it up. You can still run it through your normal movement rules without calling get().

Example:

mob/verb/wish() var/obj/O = new() //create it with loc=null if(O.Move(usr)) //and then move it into inventory usr << "Your wish has been granted!" else usr << "You are too greedy!" del O

Exit proc (atom)

See also:
Enter proc (atom)
Entered proc (atom)
Exited proc (atom)
Cross proc (atom)
Crossed proc (atom)
Uncross proc (atom)
Uncrossed proc (atom)
Move proc (movable atom)
movement_mode var (world)
Format:
Exit(atom/movable/O, atom/newloc)
Returns:
1 to permit; 0 to deny.
When:
Called when an object attempts to exit the contents list.
Args:
O: the object attempting to exit.
newloc: the object's new location.
Default action:
Turfs will call Uncross() and return that value (1 by default). All others allow the object to exit (returning 1).

By default, every atom returns 1 to allow exit, except for turfs which call Uncross() to handle it for them.

The following behavior only applies to LEGACY_MOVEMENT_MODE. In all other movement modes, the turf's contents are not taken into account. Only the result of turf.Uncross() matters.

In the default Exit handler for turfs, Uncross() is called for the turf itself and then Uncross() will also be called for any atoms in turf.contents that cover the entire tile. If any Uncross() call fails, Exit() fails too and will return 0. In games using pixel movement, Uncross() is usually called separately, but this allows projects using tile-based movement instead to benefit from Cross() and Uncross().


Exited proc (atom)

See also:
Enter proc (atom)
Entered proc (atom)
Exit proc (atom)
Cross proc (atom)
Crossed proc (atom)
Uncross proc (atom)
Uncrossed proc (atom)
Move proc (movable atom)
Format:
Exited(atom/movable/Obj, atom/newloc)
When:
Called when an object has exited from the contents list through a call to Move(). Directly setting the object's loc or step_x/y vars does not result in a call to Exited() or any other movement side-effects. The same goes for deletion of an object.
Args:
Obj: the object that exited (a mob or obj).
newloc: the object's new location.
Default action:
None for most atoms, but turfs will call Uncrossed().

MouseDown proc (atom)

See also:
Click proc (atom)
DblClick proc (atom)
MouseDown proc (client)
MouseDrag proc (atom)
MouseDrop proc (atom)
MouseEntered proc (atom)
MouseExited proc (atom)
MouseMove proc (atom)
MouseUp proc (atom)
MouseWheel proc (atom)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
show_popup_menus var (client)
Format:
MouseDown(location,control,params)
Args:
location: the turf, stat panel, grid cell, etc. in which the object was clicked
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when a mouse button is pressed while pointing to this object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through Click(), DblClick(), and MouseDrop(). The other procedures are simply available for completeness.

Note: In BYOND 3.5 this procedure took three different arguments: location, icon_x, and icon_y. Since icon_x and icon_y have been replaced, old code will need to be modified. Games compiled before this change will still work normally.


MouseDrag proc (atom)

See also:
Click proc (atom)
DblClick proc (atom)
MouseDown proc (atom)
MouseDrag proc (client)
MouseDrop proc (atom)
MouseEntered proc (atom)
MouseExited proc (atom)
MouseMove proc (atom)
MouseUp proc (atom)
MouseWheel proc (atom)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_drop_zone var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
show_popup_menus var (client)
Format:
MouseDrag(over_object,src_location,over_location,src_control,over_control,params)
Args:
over_object: the object under the mouse pointer
src_location: the turf, stat panel, grid cell, etc. from where the src object was dragged
over_location: the turf, stat panel, grid cell, etc. containing the object under the mouse pointer
src_control: The id of the skin control the object was dragged from
over_control: The id of the skin control the object was dragged over
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called while dragging this object by pressing and holding the left mouse button over the object and moving the mouse. The over_object may be null if dragging over a stat panel or over other empty space.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through Click(), DblClick(), and MouseDrop(). The other procedures are simply available for completeness.


MouseDrop proc (atom)

See also:
Click proc (atom)
DblClick proc (atom)
MouseDown proc (atom)
MouseDrag proc (atom)
MouseDrop proc (client)
MouseEntered proc (atom)
MouseExited proc (atom)
MouseMove proc (atom)
MouseUp proc (atom)
MouseWheel proc (atom)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_drop_zone var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
show_popup_menus var (client)
Format:
MouseDrop(over_object,src_location,over_location,src_control,over_control,params)
Args:
over_object: the object under the mouse pointer
src_location: the turf, stat panel, grid cell, etc. from where the src object was dragged
over_location: the turf, stat panel, grid cell, etc. containing the object under the mouse pointer
src_control: The id of the skin control the object was dragged from
over_control: The id of the skin control the object was dropped onto
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the a mouse button is released after dragging this object. The over_object may be null if dropping over a stat panel or over other empty space.


MouseEntered proc (atom)

See also:
Click proc (atom)
DblClick proc (atom)
MouseDown proc (atom)
MouseDrag proc (atom)
MouseDrop proc (atom)
MouseEntered proc (client)
MouseExited proc (atom)
MouseMove proc (atom)
MouseUp proc (atom)
MouseWheel proc (atom)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
show_popup_menus var (client)
Format:
MouseEntered(location,control,params)
Args:
location: the turf, stat panel, grid cell, etc. containing the object
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the mouse moves onto the object with no buttons pressed.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.


MouseExited proc (atom)

See also:
Click proc (atom)
DblClick proc (atom)
MouseDown proc (atom)
MouseDrag proc (atom)
MouseDrop proc (atom)
MouseEntered proc (atom)
MouseExited proc (client)
MouseMove proc (atom)
MouseUp proc (atom)
MouseWheel proc (atom)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
show_popup_menus var (client)
Format:
MouseExited(location,control,params)
Args:
location: the turf, stat panel, grid cell, etc. containing the object
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the mouse moves off of an object with no buttons pressed.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.


MouseMove proc (atom)

See also:
Click proc (atom)
DblClick proc (atom)
MouseDown proc (atom)
MouseDrag proc (atom)
MouseDrop proc (atom)
MouseEntered proc (atom)
MouseExited proc (atom)
MouseMove proc (client)
MouseUp proc (atom)
MouseWheel proc (atom)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
show_popup_menus var (client)
Format:
MouseMove(location,control,params)
Args:
location: the turf, stat panel, grid cell, etc. containing the object
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the mouse moves over the object with no buttons pressed. When the mouse moves over for the first time, MouseEntered() is called instead.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.


MouseUp proc (atom)

See also:
Click proc (atom)
DblClick proc (atom)
MouseDown proc (atom)
MouseDrag proc (atom)
MouseDrop proc (atom)
MouseEntered proc (atom)
MouseExited proc (atom)
MouseMove proc (atom)
MouseUp proc (client)
MouseWheel proc (atom)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_drop_zone var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
show_popup_menus var (client)
Format:
MouseUp(location,control,params)
Args:
location: the turf, stat panel, grid cell, etc. in which the object was clicked
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when a mouse button is released while pointing to this object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through Click(), DblClick(), and MouseDrop(). The other procedures are simply available for completeness.

Note: In BYOND 3.5 this procedure took three different arguments: location, icon_x, and icon_y. Since icon_x and icon_y have been replaced, old code will need to be modified. Games compiled before this change will still work normally.


MouseWheel proc (atom)

See also:
Click proc (atom)
DblClick proc (atom)
MouseDown proc (atom)
MouseDrag proc (atom)
MouseDrop proc (atom)
MouseEntered proc (atom)
MouseExited proc (atom)
MouseMove proc (atom)
MouseUp proc (atom)
MouseWheel proc (client)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
Format:
MouseWheel(delta_x,delta_y,location,control,params)
Args:
delta_x,delta_y: amount of wheel movement
location: the turf, stat panel, grid cell, etc. containing the object
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling

This is called when the mouse wheel is moved while over an object.

Positive values of delta_x and delta_y refer to scrolling right or up, respectively. Negative values are left and down, respectively.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.


New proc (atom)

See also:
New proc (datum)
new proc
Format:
New(loc)
(supports named arguments)
When:
Called when the object is created.
Args:
loc: The initial location.
Default action:
None.

By the time New() is called, the object has already been created at the specified location and all of its variables have been initialized. You can perform additional initialization by overriding this procedure.

Since the initial location parameter passed to new() is applied before New() is even called, there is some special handling of the loc variable when using named arguments in a call. Normally, if a procedure is overridden, named arguments in a call are matched against those in the the overridden definition. In this case, however, the loc parameter name is hard-coded. Regardless of what you call the first argument in your definition of New(), the initial location will be taken from the first positional argument, or from the argument named loc if there are no positional arguments.

The following example does some extra initialization that is not possible in the variable definition section, because it requires a runtime evaluation. This is a common reason to use New().

Example:

mob var birthdate //time stamp New() birthdate = world.realtime return ..() verb/look() set src in view() usr << "[src] was born on [time2text(birthdate,"DD-MMM-YYYY")]."

Stat proc (atom)

See also:
Stat proc (client)
stat proc
Info control (skin)
Format:
Stat()
When:
Called periodically by the client to update the stat window.
Default action:
none.

The following code could be used to display a player's current status.

Example:

mob/var health = 100 mob/Stat() stat("health",health) statpanel("Inventory",contents)

vars (atom)

Built-in atom vars:

atom/var
alpha
appearance
appearance_flags
blend_mode
color
contents
density
desc
dir
filters
gender
icon
icon_state
invisibility
infra_luminosity
loc
layer
luminosity
maptext
maptext_width
maptext_height
maptext_x
maptext_y
mouse_over_pointer
mouse_drag_pointer
mouse_drop_pointer
mouse_drop_zone var
mouse_opacity var
name
opacity
overlays
override (images only)
parent_type
pixel_x
pixel_y
pixel_w
pixel_z
plane
render_source
render_target
suffix
tag
text
transform
type
underlays
vars
verbs
x
y
z

alpha var (atom)

See also:
vars (atom)
appearance_flags var (atom)
blend_mode var (atom)
color var (atom)
Default value:
255 (opaque)
Possible values:
0 (transparent) through 255 (opaque)

Controls the opacity of the icon displayed on players' screens. A value of 128 means the atom is half-transparent, so it will have a ghostly appearance. This can be used to fade an atom in and out, especially when combined with animation. Alpha is also applied to maptext.

Overlays and images will also be affected by alpha, unless they use the RESET_ALPHA value in appearance_flags.


appearance var (atom)

See also:
vars (atom)
mutable appearance
Understanding the renderer

Every atom or image has an appearance, which controls all of the values relating to how it appears on the map. (The overlays and underlays lists are lists of appearances.) When read, this var provides a copy of the current appearance.

This value can also be used to change an atom's appearance, altering multiple values at once. Setting atom.appearance to another appearance will change all of the following values to match:

alpha
appearance_flags
blend_mode
color
desc
gender
icon
icon_state
invisibility
infra_luminosity
filters
layer
luminosity
maptext
maptext_width, maptext_height, maptext_x, maptext_y
mouse_over_pointer, mouse_drag_pointer, mouse_drop_pointer
mouse_drop_zone var
mouse_opacity var
name
opacity
overlays
override (images only)
pixel_x, pixel_y, pixel_w, pixel_z
plane
render_source, render_target
suffix
text
transform
underlays
vis_flags

Other vars that are technically part of the appearance, but don't make any sense to change when cloning, are not changed. These include density, dir, screen_loc, and verbs. However, those vars ARE copied when you assign a /mutable_appearance.

If you set atom.appearance to another atom, the other atom's appearance will be copied.


appearance_flags var (atom)

See also:
vars (atom)
alpha var (atom)
color var (atom)
transform var (atom)
color var (client)
Gliding
movement_mode var (world)
Understanding the renderer
Default value:
0
Possible values:
Any combination of:
LONG_GLIDE: Diagonal glides take as long as cardinal ones
RESET_COLOR: If this is an overlay/image/etc., ignore the parent's color
RESET_ALPHA: If this is an overlay/image/etc., ignore the parent's alpha value
RESET_TRANSFORM: If this is an overlay/image/etc., ignore the parent's transform
NO_CLIENT_COLOR: Ignore client.color
KEEP_TOGETHER: Draw this icon along with its overlays and underlays, as one unit
KEEP_APART: Detach from a parent icon that uses KEEP_TOGETHER
PLANE_MASTER: Groups all other icons in the same plane
TILE_BOUND: Avoids more accurate visibility calculations
PIXEL_SCALE: Use point sampling when transforming this icon
PASS_MOUSE: If this icon has a render_source, pass mouse any hits to the render source
TILE_MOVER: This atom is always locked to the grid

The appearance_flags value controls miscellaneous behavior of an atom or appearance that doesn't make sense to handle in any other var.

These values are bitflags, and can be combined with the + or | operator.

LONG_GLIDE

Gliding is normally done by Euclidean (straight-line) distance, so diagonal gliding across a square tile takes about 41% longer, since the distance is multiplied by sqrt(2). With LONG_GLIDE, the dominant X or Y direction of the glide is used to adjust the glide size so it takes just as long as if the object were gliding in a cardinal direction.

RESET_COLOR, RESET_ALPHA, RESET_TRANSFORM

These flags cause this overlay not to inherit aspects of its parent object. Ordinarily, transforms on a parent get applied to overlays too, as does color.

All of these flags are ignored if KEEP_TOGETHER is used on the parent (and this object does not override with KEEP_APART), since then the parent icon along with all of its overlays get drawn to a single surface and color, transform, etc. are applied afterward.

NO_CLIENT_COLOR

The value of client.color is normally applied to all icons. This flag says that the icon is an exception. Generally client.color has been superseded by the use of plane masters anyway.

The NO_CLIENT_COLOR flag is inherited by overlays and images automatically unless they have the RESET_COLOR flag. It is also basically meaningless when used on an overlay that's inside of a KEEP_TOGETHER group, since the client's color is applied to the entire group.

KEEP_TOGETHER

This flag is used to force the overlays and underlays of this icon (its "children") to be drawn with it all at once, not each icon individually. One reason you might want to do this is if your player's icon uses overlays for hair and equipment, and you want to change the alpha value to make them fade out. With regular drawing, changing the parent icon's alpha means that each individual icon becomes translucent; with KEEP_TOGETHER, the whole combination fades as one unit. Because this incurs some small overhead, it should be avoided for atoms that do not need it.

Any child appearances underneath KEEP_TOGETHER use NO_CLIENT_COLOR automatically, and RESET_COLOR, RESET_ALPHA, and RESET_TRANSFORM become meaningless. Use KEEP_APART with them if you want to use those flags.

Icons that are in a different plane from the parent icon will automatically have KEEP_APART set and therefore won't be included.

KEEP_APART

If this appearance is a child of something that uses KEEP_TOGETHER, it will be separated out from the main icon and drawn separately. This may be useful for things such as health meters, for instance.

This flag is automatically applied to icons that are on a different plane from their parents.

PLANE_MASTER

Use this flag to group all icons in the same plane and draw them on a temporary surface the size of the whole screen, and then that image is drawn over the existing scene. This is useful for post-processing effects, like lighting. The plane master's icon is not drawn, but its color, transform, and blend_mode are all taken into account when drawing.

Example

obj/lighting_plane screen_loc = "1,1" plane = 2 blend_mode = BLEND_MULTIPLY appearance_flags = PLANE_MASTER | NO_CLIENT_COLOR // use 20% ambient lighting; be sure to add full alpha color = list(null,null,null,null,"#333f") mouse_opacity = 0 // nothing on this plane is mouse-visible image/spotlight plane = 2 blend_mode = BLEND_ADD icon = 'spotlight.dmi' // a 96x96 white circle pixel_x = -32 pixel_y = -32 mob/Login() ..() client.screen += new/obj/lighting_plane overlays += /image/spotlight

In the example, all objects in plane 2 are lights. They're added together, and then the whole image is put through the color matrix, then multiplied over the rest of the scene below. This will darken everything that doesn't have a spotlight overlay, but anywhere a spotlight exists will have a circle of light.

The example also makes a point of adding full alpha to the plane, because a plane is fully transparent by default. However, it's usually a better idea not to mess with the alpha color, and instead use another icon, scaled to the appropriate size, as a backdrop.

The mouse_opacity set by the plane master will determine how the mouse interacts with objects on the plane. A value of 0 will mean everything in the plane is invisible to the mouse; 1 means the plane is mouse-invisible but the objects in it use their own mouse_opacity. 2 is the same except the plane itself is mouse-visible.

TILE_BOUND

There are many ways an object may be shifted out of the normal bounds of the tile it's on: a large icon, pixel offsets, step offsets, and transform. Ordinarily it's desirable to be able to see the object if it touches any visible turf. However, in some cases it's more desirable to only show the object if its actual loc is in view. The TILE_BOUND flag will accomplish that. This flag is inherited by images and overlays.

PIXEL_SCALE

Normally if an icon is transformed via atom.transform, it uses bilinear texture sampling which produces a nice smooth effect. If you want a granular pixel-art effect instead, PIXEL_SCALE will do that for you by using nearest-neighbor sampling.

PASS_MOUSE

If this object has a render_source it will take on the rendered appearance of another object (source). This is just a visual copy, so the mouse still interacts with this object, not the source. The PASS_MOUSE flag causes any mouse interaction to happen with the source instead of this object.

TILE_MOVER

This flag indicates this atom is locked to the tile grid as it would be in TILE_MOVEMENT_MODE, regardless of the setting of world.movement_mode. In this way, pixel movers and tile movers can coexist.


blend_mode var (atom)

See also:
vars (atom)
alpha var (atom)
color var (atom)
appearance_flags var (atom)
Default value:
0 (none/overlay)
Possible values:
BLEND_DEFAULT (0)
BLEND_OVERLAY
BLEND_ADD
BLEND_SUBTRACT*
BLEND_MULTIPLY*†
BLEND_INSET_OVERLAY*†

[* This blend type appears only when using graphics hardware mode. It is also not visible in the map editor.]
[ Since the alpha of the icon underneath is used for alpha masking, mouse hits take it into account.]

Controls the way the atom's icon is blended onto the icons behind it. The blend mode used by an atom is inherited by any attached overlays, unless they override it. BLEND_DEFAULT will use the main atom's blend mode; for the atom itself, it's the same as BLEND_OVERLAY.

BLEND_OVERLAY will draw an icon the normal way.

BLEND_ADD will do additive blending, so that the colors in the icon are added to whatever is behind it. Light effects like explosions will tend to look better in this mode.

BLEND_SUBTRACT is for subtractive blending. This may be useful for special effects.

BLEND_MULTIPLY will multiply the icon's colors by whatever is behind it. This is typically only useful for applying a colored light effect; for simply darkening, using a translucent black icon with normal overlay blending is a better option.

BLEND_INSET_OVERLAY overlays the icon, but masks it by the image being drawn on. This is pretty much not at all useful directly on the map, but can be very useful for an overlay for an atom that uses KEEP_TOGETHER (see appearance_flags), or for the layering filter.


color var (atom)

See also:
vars (atom)
alpha var (atom)
appearance_flags var (atom)
blend_mode var (atom)
color var (client)
rgb proc
MapColors proc (icon)
Default value:
null (white)
Possible values:
null (white)
any color generated by rgb() (e.g., "#00ff00" for green)
a color matrix (in list form)

Controls the color of the icon displayed on players' screens. This color is multiplied by the icon, so that a white icon will become this color. The color multiplier is also applied to maptext.

If you include an alpha component in the color, the atom's alpha var will be set at the same time.

Overlays and images will also be multiplied by this color, unless they use the RESET_COLOR value in appearance_flags.

The color value can be set to a color matrix, which is a list of values. This allows for more complex transformations such as adding or subtracting color, inverting the color, turning to grayscale, shifting hue, etc. Using an RGB-only color matrix will include the existing alpha value in the matrix.

When reading the color var, if it is a matrix it will be read out as a list with 20 items (full RGBA format). That list is a copy, so if you save it and make changes to that list later it will not impact the actual color of the atom. This also means you can't use color[9] = 0.5; you would have to grab the value of color first, make sure it's a list, change it, and then assign the changed list back to the color var.


contents list var (atom)

See also:
Enter proc (atom)
Entered proc (atom)
Exit proc (atom)
Exited proc (atom)
locs list var (movable atom)
Pixel movement
list
loc var (atom)
Default value:
List of contained objects.

Except in the case of areas, this list is always restricted to objs and mobs (ie movable objects). Only direct contents are listed. Items inside of a bag object, for example, would not show up in the mob's contents list.

The contents of areas are a little different. The turfs contained in the area are in the list along with any objs or mobs directly contained by those turfs.

If a movable atom uses the bound vars to change its physical size, or step_x or step_y to change its position, it may cover more than one turf. In that case, those turfs' contents won't just contain anything directly in them, but also any atoms overhanging them. I.e., if a turf is in a mob's locs list, then the mob is in that turf's contents list. (See locs for more information.)

Note: Looping through all of the atoms, or even just turfs, in a particular area actually loops through every turf in the world. E.g., for(var/turf/T in area). The engine will check each turf to see if it belongs to that area, and then includes the turf and/or its contents in the results depending on what the loop is looking for. This also applies to any situation where you might grab area.contents as a list, e.g. area.contents.Copy(). Therefore in a large world, it's advisable not to loop through area contents at all.


density var (atom)

See also:
Enter proc (atom)
Entered proc (atom)
Exit proc (atom)
Exited proc (atom)
Default value:
0 (1 for mobs)

This turns the object's density on or off (1 or 0). Two dense objects may not occupy the same space in the standard movement system.


desc var (atom)

Default value:
null

This is the description of the object.

Example:

mob/verb/look(atom/O in view()) if(O.desc) usr << O.desc else usr << "It's just \an [O]."

dir var (atom)

See also:
Move proc (movable atom)
icon var (atom)
turn proc
stddef.dm file
Default value:
SOUTH
Possible values:
NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST

This is the direction that the object is facing. This has little effect unless the object's icon is directional. In the case of a directional icon, this selects the corresponding orientation from the icon file.

An icon file with only four (cardinal) directions makes the choice of orientation ambiguous when the true direction is a diagonal. In that case, of the two possibilities, the one closest to the previous orientation is displayed. Sounds complicated, but it's what one would naturally expect.


filters var (atom)

See also:
appearance_flags var (atom)
filter proc
animate proc
Filter effects
Default value:
empty list

This var is a list of graphical filters to use for post-processing effects, applied in order. You can assign this value a list, an individual filter, or null to empty it.

Example:

obj/blurry filters = filter(type="blur", size=1)

Atoms with the KEEP_TOGETHER flag will apply their filters after the composite image has been drawn. Filters will also apply to any maptext the atom has.

See the filters section for more information on individual filters.


gender var (atom)

See also:
macros (text)
name var (atom)
Default value:
"neuter"

This sets the object's gender. This influences text macros like \he, which may expand to "it", "he", "she", or "they". Valid values are:

"neuter" "male" "female" "plural" These are also defined as constants, which may help prevent typos, since the compiler will complain if it doesn't recognize what you type: NEUTER MALE FEMALE PLURAL

icon var (atom)

See also:
icon proc
icon_state var (atom)
icons
overlays var (atom)
underlays var (atom)
load_resource proc
Default value:
null

This is the icon file that will be used to represent the object on graphical clients.

Example:

turf/wall icon = 'wall.dmi'

You can also assign this to an external file at run-time with an expression such as file("wall.dmi"), but you would only want to do that when the other method is not possible, because it requires addition of the file to the resource cache, which can take a little time.

When this variable is set to any dynamically created icon object, that object gets dumped into the world's resource cache (the .rsc file), and a reference to that cached file is assigned to atom.icon. In other words, don't expect comparisons such as usr.icon == MyDynamicallyCreatedIcon to work unless you have used fcopy_rsc() to get a cache reference to your dynamically created icon first. This is almost never an issue, so don't worry about it if none of that made any sense to you!


icon_state var (atom)

See also:
flick proc
icon var (atom)
icon_states proc
Default value:
null

Icons may appear differently depending on the icon state. For example, turf door icons could have "open" and "closed" states. If a state is specified that does not exist in the icon file, the default null state will be displayed if it exists.

Example:

turf/door icon_state = "closed" density = 1 verb open() set src in view(1) icon_state = "open" density = 0 close() set src in view(1) icon_state = "closed" density = 1

infra_luminosity var (atom)

See also:
luminosity var (atom)
see_infrared var (mob)
sight var (mob)
view proc
Default value:
0

This causes the object to be visible in the dark to mobs that can see infrared light. Nothing but the object itself is lit up by the infrared emission. The scale is identical to luminosity: 1 makes it visible only from the same location; 2 makes it visible from a neighboring position; and so on.


invisibility var (atom)

See also:
invisibility setting (verb)
opacity var (atom)
see_invisible var (mob)
sight var (mob)
view proc
Default value:
0
Possible values:
0 to 101

This determines the object's level of invisibility. The corresponding mob variable see_invisible controls the maximum level of invisibility that the mob may see.

A value of 101 is absolutely invisible, no matter what, and it is filtered from all lists of possible values for verb arguments. This is intended for objects that exist purely for some internal purpose, such as "verb containers".


layer var (atom)

See also:
overlays var (atom)
plane var (atom)
z var (atom)
map_format var (world)
BACKGROUND_LAYER
EFFECTS_LAYER
TOPDOWN_LAYER
Understanding the renderer
Default value:
1 (AREA_LAYER)
2 (TURF_LAYER)
3 (OBJ_LAYER)
4 (MOB_LAYER)

This numerical value determines the layer in which the object is drawn on the map. By default, the order is area, turf, obj, mob, followed by missiles and images (in FLY_LAYER, which is 5).

Example:

turf archway layer = MOB_LAYER+1 //overhead

When making objects to be used as graphical overlays, you should also be aware of the special FLOAT_LAYER value. This causes the overlay (or underlay) to be in the same drawing layer as the base object, no matter how that layer changes after the addition of the overlay. Otherwise, the overlay object's own drawing layer is used.

The actual drawing order of icons may change depending on world.map_format. An isometric map for instance has to display tiles that are "closer" to the viewer in front of tiles that are in the back, so the layer var takes a backseat to the needs of the map. If you use the TOPDOWN_MAP or TILED_ICON_MAP map formats, the layer is more important.

If you are using a world.map_format that does not display topdown, such as ISOMETRIC_MAP or SIDE_MAP, then you can use a special layer for showing certain portions of the map in topdown mode. For those parts of the map, you can add TOPDOWN_LAYER to every atom's layer to make the atom appear in topdown mode. This is for special cases, like for instance a battle map in an RPG, where a regular topdown view is preferable to the special mapping used by the rest of the game. It is recommended that you use TOPDOWN_LAYER with every atom in that portion of the map, since topdown and isometric maps for instance don't mix. If you use TOPDOWN_LAYER, it is best to use a square size in world.icon_size if any of these atoms will be moving around.

Another special layer, EFFECTS_LAYER, is also available. Icons that use this layer will display above icons that don't. TOPDOWN_LAYER will then display above that. This layer is useful for situations such as using a floating name or health meter overlay on a mob in isometric mode. When using EFFECTS_LAYER, other icons on the regular map won't cover the overlay. (It is preferable to use atom.plane for this, when possible.)

Finally there is BACKGROUND_LAYER. Adding this to an atom's layer will make it appear below any atoms that do not use BACKGROUND_LAYER. (It is preferable to use atom.plane when possible.)

The atom.plane var takes priority over layer. This is the preferred method of handling background and effects.


loc var (atom)

See also:
contents list var (atom)
x var (atom)
y var (atom)
z var (atom)
Default value:
The location of the object or null if there is none.

The container is always an atom (or null). For areas, this value is always null, since an area may not be contained by any other object.


luminosity var (atom)

Default value:
0
1 (areas)

This sets the object's luminosity (how far it casts light). It must be an integer in the range 0 to 6.

Areas are a little different. Any non-zero value in an area results in all objects within the area being bathed in light.


maptext var (atom)

See also:
maptext_width var (atom)
maptext_height var (atom)
maptext_x var (atom)
maptext_y var (atom)
overlays var (atom)
image objects
pixel_x var (atom)
pixel_y var (atom)
pixel_w var (atom)
pixel_z var (atom)
Default value:
null

This is optional text that will be displayed in the same position as the atom. If an atom has both an icon and maptext, the text will be displayed in front of the icon. Usually however, this is something that would be added to an overlay or image object, which can then be positioned with pixel offsets.

Map text is constrained to the bounds set by maptext_width and maptext_height, which default to a single icon in size. It can be offset by maptext_x and maptext_y.

Text can use HTML and CSS, mostly the same limited subset supported by regular text output, and different styles can be used in the same block of text. In addition, alpha colors can also be used, by specifying a color as #rrggbbaa instead of just #rrggbb. (Alpha transparency will be ignored when the map is drawn without hardware rendering, so anything below 50% opacity is not displayed in those cases.)

Maptext supports links with the <a> tag. Left-clicking on a link will follow the link, but also generate other events such as MouseDown or Click.


maptext_width var (atom)

See also:
maptext var (atom)
maptext_x var (atom)
maptext_y var (atom)
maptext_height var (atom)
icon_size var (world)
Default value:
32 (depends on world.icon_size)

This is the width of the text shown in the maptext var. By default, it uses the icon width provided in world.icon_size.


maptext_height var (atom)

See also:
maptext var (atom)
maptext_width var (atom)
maptext_x var (atom)
maptext_y var (atom)
icon_size var (world)
map_format var (world)
Default value:
32 (depends on world.icon_size)

This is the height of the text shown in the maptext var. The default value depends on world.icon_size and world.map_format. In a topdown (default) or tiled map_format, the icon height is used. In other map views, tile "footprints" are square and height is irrelevant, so the default will be the icon width instead.)


maptext_x var (atom)

See also:
maptext var (atom)
maptext_width var (atom)
maptext_height var (atom)
maptext_y var (atom)
icon_size var (world)
Default value:
0

Maptext, if used, is offset by this many pixels to the right.


maptext_y var (atom)

See also:
maptext var (atom)
maptext_width var (atom)
maptext_height var (atom)
maptext_x var (atom)
icon_size var (world)
Default value:
0

Maptext, if used, is offset by this many pixels upward.


mouse_drag_pointer var (atom)

See also:
MouseDrag proc (atom)
MouseDrop proc (atom)
mouse_drop_pointer var (atom)
mouse_drop_zone var (atom)
mouse_over_pointer var (atom)
mouse_pointer_icon var (client)
Default value:
MOUSE_INACTIVE_POINTER (0)

This defines how the mouse looks when dragging this object. Assigning this to MOUSE_ACTIVE_POINTER (1) enables the default dragging indicator.

This variable may also be set to any of the other built-in mouse pointers, or a custom icon or icon state. If an icon state is specified, this is applied against the object's main icon to find a custom pointer.

Note that all mouse pointers are purely visual indicators. They do not effect what objects may actually be manipulated with the mouse. You control all of the real behavior in the associated procedures.


mouse_drop_pointer var (atom)

See also:
MouseDrag proc (atom)
MouseDrop proc (atom)
mouse_drop_pointer var (atom)
mouse_drop_zone var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
mouse_pointer_icon var (client)
Default value:
MOUSE_ACTIVE_POINTER (1)

This defines how the mouse looks when dragging this object over another object that has mouse_drop_zone set. The default value enables the addition of a standard "droppable" indicator to whatever mouse_drag_pointer is (unless mouse_drag_pointer is turned off).

This variable may also be set to any of the other built-in mouse pointers, or a custom icon or icon state. If an icon state is specified, this is applied against the object's main icon to find a custom pointer.

Note that all mouse pointers are purely visual indicators. They do not effect what objects may actually be manipulated with the mouse. You control all of the real behavior in the associated procedures.


mouse_drop_zone var (atom)

See also:
MouseDrag proc (atom)
MouseDrop proc (atom)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
mouse_pointer_icon var (client)
Default value:
0

Setting this to 1 indicates that this object is a valid site on which to drop other objects. While dragging, mouse_drop_cursor of the object being dragged will become active in this case. Note that this is a purely visual effect. It does not control what the user may do with the mouse. You control the real behavior with the associated procedures.


mouse_opacity var (atom)

See also:
mouse handling
overlays var (atom)
underlays var (atom)
vis_contents var (atom)
render_source var (atom)
Default value:
1
Possible values:
0 // transparent to mouse
1 // mouse-opaque where icon is also opaque
2 // completely mouse-opaque

This may be used to control how mouse operations on an object are interpreted. A click or mouse movement over an object's icon normally applies to that object only if it is the topmost object that is not transparent at the position of the mouse. Setting mouse_opacity to 0 would cause the object to be ignored completely, and setting it to 2 causes it to always be chosen over any lower-level objects, regardless of the transparency of its icon.

Note that overlays and underlays are not distinct objects, so their mouse_opacity is completely ignored in favor of the object they're attached to. The same applies to image objects, which act like special overlays as well. Visual contents, on the other hand, are separate objects that can act like overlays in some ways, but because they're separate their mouse_opacity is taken into account.

When this is applied to a PLANE_MASTER object (see appearance_flags), a value of 0 means everything on the plane is mouse-transparent. 1 means everything on the plane is mouse-visible (using the objects' normal mouse_opacity), but the plane master itself is not. 2 means everything on the plane is mouse-visible, and so is the plane master.


mouse_over_pointer var (atom)

See also:
Click proc (atom)
MouseEntered proc (atom)
MouseExited proc (atom)
MouseMove proc (atom)
mouse_drag_pointer var (atom)
mouse_drop_pointer var (atom)
mouse_drop_zone var (atom)
mouse_opacity var (atom)
mouse_pointer_icon var (client)
Default value:
MOUSE_INACTIVE_POINTER (0)

This defines how the mouse looks when no buttons are pressed and it is held over this object. Assigning this to MOUSE_ACTIVE_POINTER (1) enables the default indicator that there is something special under the mouse (crosshairs).

This variable may also be set to any of the other built-in mouse pointers, or a custom icon or icon state. If an icon state is specified, this is applied against the object's main icon to find a custom pointer.

Note that all mouse pointers are purely visual indicators. They do not effect what objects may actually be manipulated with the mouse. You control all of the real behavior in the associated procedures.


name var (atom)

See also:
gender var (atom)
Default value:
The name of the object type with underscores converted to spaces.

opacity var (atom)

Default value:
0

This turns the object's opacity on or off (1 or 0). Opaque objects block light.


overlays var (atom)

See also:
underlays var (atom)
icon var (atom)
layer var (atom)
list
image objects
vis_contents var (atom)
Understanding the renderer
Default value:
empty list

This is a list of simple icons which are displayed on top of the object's main icon.

The individual items in the list may not be directly accessed, since they are stored in a special internal format. However, the list operators +=, -=, and the procedures Add, Remove, and Cut work normally.

Example:

turf/verb/AddOverlay(I as icon) overlays += I turf/verb/RemoveOverlay(I as icon) overlays -= I

The data types that may be used as overlays are icons, icon states (text strings), objects, and object types. When an icon state is used, the corresponding image in the object's icon is displayed. When another object is used as an overlay, a static "snapshot" of the object is taken at the time when the overlay is created. Future changes to the object will not change the appearance of the overlay, except that in some cases the overlay may inherit things from the base object like its icon (if left empty), direction, and moving state.

Overlays have their own independent drawing layer. It is normally the special value FLOAT_LAYER, which makes them float above the base object. If the overlay is a snapshot of another object, the drawing layer of that object is used (and in that case, the overlay can appear beneath the object if its layer is lower). The important advantage of using FLOAT_LAYER is that if the layer of the base object changes, the overlays will move with it into the new layer.

Any negative number may be used in place of FLOAT_LAYER (which happens to be -1). They all cause the same "floating" behavior. However, the overlays are ordered amongst themselves according to their own relative layer values (-2 below -1 and so on). This may be useful if you have several classes of overlays that should always appear in a certain order, because you would not have to worry about the order in which you add them to the list.

Example:

var/const ARMOR_LAYER = FLOAT_LAYER-1 CLOTHES_LAYER = FLOAT_LAYER-2 obj/overlay armor icon = 'armor.dmi' layer = ARMOR_LAYER clothes icon = 'clothes.dmi' layer = CLOTHES_LAYER mob/verb wear_clothes() overlays += /obj/overlay/clothes wear_armor() overlays += /obj/overlay/armor remove_clothes() overlays -= /obj/overlay/clothes remove_armor() overlays -= /obj/overlay/armor

That example used object types, but you can use instances of objects as well. Rather than using different "float" layers, you can also just make your own list of overlays with the order you want and assign that to the actual overlays list.

Example:

mob/var boots clothes armor mob/proc ShowOverlays() var/L[0] if(boots) L += boots if(clothes) L += clothes if(armor) L += armor overlays = L

override var (atom)

Default value:
0

Currently this only applies to images.

If you attach an image to an atom, normally it is seen only in addition to the atom's regular icon. If the image's override var is 1, it will be seen in place of the original atom (and its overlays). It will inherit the atom's color, alpha, transform, and appearance_flags, unless its own appearance_flags say otherwise.

If the image has a specific name and/or suffix value, those will override the parent atom too. Leaving them blank will let the original atom take precedence.


pixel_x var (atom)

See also:
animate_movement var (movable atoms)
glide_size var (movable atoms)
pixel_y var (atom)
pixel_w var (atom)
pixel_z var (atom)
icon_size var (world)
map_format var (world)
Pixel movement
Default value:
0

This displaces the object's icon on the x-axis by the specified number of pixels. In a project with a standard 32x32 tile size, this can range from -32 to +32. (You can get away with larger displacements, but they are not guaranteed to work for objects off the edge of the map.)

Since overlays and images can each have their own additional displacements, this makes it possible to create visual effects that extend beyond the object's own cell in the turf grid, but which automatically move around with the object.

This effect is purely visual and does not influence such things as movement bumping or view() range calculations.


pixel_y var (atom)

See also:
animate_movement var (movable atoms)
glide_size var (movable atoms)
pixel_x var (atom)
pixel_w var (atom)
pixel_z var (atom)
icon_size var (world)
map_format var (world)
Pixel movement
Default value:
0

This displaces the object's icon on the y-axis by the specified number of pixels. In a project with a standard 32x32 tile size, this can range from -32 to +32. (You can get away with larger displacements, but they are not guaranteed to work for objects off the edge of the map.)

Since overlays and images can each have their own additional displacements, this makes it possible to create visual effects that extend beyond the object's own cell in the turf grid, but which automatically move around with the object.

This effect is purely visual and does not influence such things as movement bumping or view() range calculations.


pixel_w var (atom)

See also:
animate_movement var (movable atoms)
glide_size var (movable atoms)
pixel_x var (atom)
pixel_y var (atom)
pixel_z var (atom)
icon_size var (world)
map_format var (world)
Default value:
0

This displaces the object's icon horizontally by the specified number of pixels. This is meant to be used in situations where world.map_format is used to display something other than a top-down form, for instance in an isometric or side-view display. In a top-down mode pixel_w behaves the same as pixel_x, except that it does not rotate with changes to client.dir.

This effect is purely visual and does not influence such things as movement bumping or view() range calculations.


pixel_z var (atom)

See also:
animate_movement var (movable atoms)
glide_size var (movable atoms)
pixel_x var (atom)
pixel_y var (atom)
pixel_w var (atom)
icon_size var (world)
map_format var (world)
Default value:
0

This displaces the object's icon vertically by the specified number of pixels. This is meant to be used in situations where world.map_format is used to display something other than a top-down form, for instance in an isometric or side-view display. In a top-down mode pixel_z behaves the same as pixel_y, except that it does not rotate with changes to client.dir.

This effect is purely visual and does not influence such things as movement bumping or view() range calculations.


plane var (atom)

See also:
layer var (atom)
appearance_flags var (atom)
vis_contents var (atom)
map_format var (world)
Understanding the renderer
Default value:
FLOAT_PLANE
Possible values:
-10000 to 10000 (integers only), FLOAT_PLANE+p

The value of plane overrides layer, and is mainly used for non-topdown map formats like isometric. Positive values are drawn on top, and negative values are drawn below. This mostly deprecates EFFECTS_LAYER and BACKGROUND_LAYER, but they can still be useful when using PLANE_MASTER for effects (see appearance_flags).

The special value FLOAT_PLANE can be used for images and overlays, to take on the plane of the parent atom. Whenever an icon or icon_state is used directly as an overlay, this is its plane. If there is no parent atom, the plane is 0.

You can also use FLOAT_PLANE as a relative value, so FLOAT_PLANE+1 adds 1 to the parent atom's plane. This may be useful for some applications where an object is included in visual contents. The added value should still be kept in the range of -10000 to 10000, or preferably much smaller.


render_source var (atom)

See also:
render_target var (atom)
appearance_flags var (atom)
Default value:
null
Possible values:
Any non-empty text string

If any icon uses render_source, the renderer will look for another icon with a matching render_target value on the visible map, and draw that in place of the icon/icon_state/dir that it normally would. The same render target might be used as a source multiple times, and for a complex image this can save some rendering time. This is also usable for special effects such as filters that might require copies of an image.

Note: The corresponding render_target must be visible to the player for a render source to be used.

Other vars that would normally affect the appearance of this icon, such as color, transform, filters, appearance_flags, etc. are all applied. Additionally, if this object has overlays, underlays, or visual contents, those will still be drawn as well.

If an entire PLANE_MASTER was the render source, some vars like pixel_x/y/w/z will not apply, but you can use transform.

Note: Any mouse hits on this object belong to the object itself, not to the object used in the render_source or its children. If you want mouse clicks and other behavior to go to the source, use the PASS_MOUSE appearance flag.


render_target var (atom)

See also:
render_source var (atom)
appearance_flags var (atom)
color var (atom)
filters var (atom)
transform var (atom)
Default value:
null
Possible values:
Any non-empty text string

If any icon uses render_target, and another icon in the scene has a matching render_source, this icon will be drawn to a temporary image called a "slate", which can be reused mutiple times for faster drawing and for special effects.

If the render_target value starts with an asterisk ("*"), it will not be drawn on the map, but will still be drawn to a slate for reuse.

Other vars that would normally affect the appearance of this icon, such as color, transform, filters, appearance_flags, etc. are all applied when drawing to the slate. Additionally, if this object has overlays, underlays, or visual contents and uses the KEEP_TOGETHER flag to group all of the icons together, those will also be included in the slate.

If the render target is a PLANE_MASTER, vars like pixel_x/y/w/z will not apply when it is re-drawn as a render_source.

To use a render_target, the object it belongs to must be within the visible part of the map, or in the HUD, etc., so that it would be visible to the user under normal circumstances. If not, it will not be included in the render process and therefore it can't be reused as a render_source.

Additionally, if you use multiple map controls, a given render target can only be used as a source on the same map control where it appears. This is because each map is rendered separately.


suffix var (atom)

Default value:
null

This is an optional text string that follows the object's name in the stat panels. For example, items in an inventory list are displayed as an icon, a name, and a suffix.


text var (atom)

Default value:
The first letter of the object's name.

This is the character used to represent the object on text clients.

Entering several characters produces a text movie (the state of the art!). In that case, each character is displayed for a 10th of a second.

HTML tags in the text can be used to modify the colors of the text characters. As a convenience, the <font> tag may include a bgcolor attribute, so you don't have to do a CSS style setting to accomplish the same thing.

Example:

world maxx = 10 maxy = 10 area text = "<font bgcolor=blue> " turf text = "<font color=#F00>....<font color=#C00>.."

The example above produces a map with a blue background (from the area) and turfs (depicted by ".") that flash from bright red to a shorter span of light red.

Note that in order to see text icons, the user must switch to the text map in Dream Seeker. If your DM code never does anything with the icon variable, then this is the default configuration. Such applications are known as advanced iconic text games:)


transform var (atom)

See also:
vars (atom)
matrix

An atom can be made to appear rotated, scaled, and/or translated (moved) by using affine transforms. This takes a matrix and multiplies the x and y positions of the icon's corners like so:

          a d 0
x y 1  *  b e 0  =  x' y' 1
          c f 1

This is equivalent to:

x' = a*x + b*y + c
y' = d*x + e*y + f

You do not need to understand matrix math to use transforms, because you can use the matrix datum to do this for you.

Transformations are relative to the center of the icon. They do not apply to maptext.

Examples:

// Rotate the atom by 45° clockwise src.transform = turn(src.transform, 45) // OR var/matrix/M = matrix() M.Turn(45) src.transform = M // Scale the atom by 2x2 src.transform *= 2 // OR var/matrix/M = matrix() M.Scale(2,2) src.transform = M

Whenever you read the atom.transform var, you will get a copy of the atom's current transformation. Whenever you assign a value to the var, you will update the transformation.

Assigning null to atom.transform will revert the atom to using no transformation at all. It is also legal to assign a list with six values, which is equivalent to using a matrix.


underlays var (atom)

See also:
icon var (atom)
list
overlays var (atom)
Understanding the renderer
Default value:
empty list

This is a list of icons which are displayed underneath the object's main icon. Since these are basically the same as overlays, see overlays for more detailed information.

The only real differences between items in the underlays list vs. the overlays list is that they're processed first, and if they use FLOAT_LAYER (or any other negative layer value) they'll appear below the object instead of above it. For this reason, the underlays list isn't used nearly as much as overlays since it's easier to throw most things into the overlays list.

When multiple turfs are stacked on top of one another in the map editor, there is actually only one turf (the topmost) and the rest are all underlays.


verbs list var (atom)

See also:
list
typesof proc
Default value:
The list of verbs defined for the object's prototype.

This is a list of the object's verbs. Initially, it contains all of the verbs defined in the prototype. It may be used to add and remove verbs at runtime.

Note that this variable is not automatically saved when the object is written to a savefile. That behavior may change in the future. In the mean time, you must save any necessary changes yourself or they will not be preserved when the object is loaded.

Example:

mob/proc/kazaam() usr << "Kazaam!" mob/verb/add_kazaam() verbs += /mob/proc/kazaam mob/verb/remove_kazaam() verbs -= /mob/proc/kazaam

vis_contents var (atom)

See also:
vis_locs var (atom)
vis_flags var (atom)
image objects
HUD / screen objects
Default value:
Empty list.

Turfs, movable atoms, and images can be given a list of atoms (limited to turfs and movable atoms) that are attached to them visually, like an overlay or image object, but act independently and have their own identity. These are visual contents. The purpose of visual contents is to provide an alternative system to overlays and images, with a little more flexibility for various special effects.

For example, a mob with an obj in its visual contents will show the obj as if it's following the mob around like an overlay, but clicking on the obj will not—unlike an overlay or an image object—count as a click on the mob. Likewise, the obj will retain its own separate mouse_opacity setting, which is not true of regular overlays.

An atom that appears on the map normally can still be in the visual contents of another atom. However it will not apply gliding and step offsets here. Also, considerations like visibility will not apply.

If a turf is in an atom's visual contents, the turf and all of that turf's contents will be displayed. (In the case of big atoms, or movable atoms with step offsets, only atoms that actually have that turf as their loc will appear. "Overhangers" will not.) Gliding and step offsets will be applied to that turf's contents normally; but again visibility, opacity, etc. will not be considered. (If you have one or more turfs in visual contents, an object gliding to a new turf outside of that list will not be shown because it's already technically on the new turf.)

If multiple turfs are present in visual contents, they will be offset as needed (relative to the southwest-most turf) to appear in the correct positions. That is, pixel_x and pixel_y offsets will be applied automatically, so if you add an entire block to visual contents (be aware this will impact performance), you don't have to do anything else to make the block appear normal.

You can alter some aspects of how an object behaves when in visual contents by changing its vis_flags var. In particular this is useful if you want an object to behave more like an overlay, inheriting aspects of its parent object or even acting like a part of that object instead of an independent one. Also this can make an object act like an underlay instead of an overlay when using a floating layer.

Visual contents do not impact the results of view() or range(), or verb availability, in any way. This is strictly a visual effect.

Being in a visual contents list counts as a reference for anything in the list, the same way that being on the map or inside of a movable counts as a reference.


vis_flags var (atom)

See also:
vis_contents var (atom)
vis_locs var (atom)
Default value:
0
Possible values:
Any combination of:
VIS_INHERIT_ICON: Use the parent object's icon.
VIS_INHERIT_ICON_STATE: Use the parent object's icon_state.
VIS_INHERIT_DIR: Use the parent object's dir.
VIS_INHERIT_LAYER: Use the parent object's layer.
VIS_INHERIT_PLANE: Use the parent object's plane.
VIS_INHERIT_ID: Use the parent object's identity, so it acts like part of the same object.
VIS_UNDERLAY: Act as if this is at the bottom of the parent's underlays list instead of overlays (only relevant if using VIS_INHERIT_LAYER or a FLOAT_LAYER).
VIS_HIDE: Do not show this object in visual contents at all.

This is a set of flags that determine how this object will behave when it is in another object's visual contents.

Because only turfs, objs, and mobs can be in visual contents, this var belongs only to those types.

The VIS_INHERIT_ID flag effectively makes this object act like an ordinary overlay when in visual contents. This means its mouse_opacity will be meaningless, for example.

Sometimes it's desirable for an object not to show up in visual contents, so VIS_HIDE will prevent that. The flag applies even if this object appears indirectly, like if it's in the contents of a turf that is in the visual contents of something else.

Note: Using any of the the flags VIS_INHERIT_ICON, VIS_INHERIT_ICON_STATE, VIS_INHERIT_DIR, or VIS_INHERIT_ID will cause movable atoms to inherit the "moving" flag of their container that appears during gliding. E.g., if your mob is walking, anything in its visual contents that uses these flags will use a moving icon state instead of a non-moving icon state, when available.


vis_locs var (atom)

See also:
vis_contents var (atom)
vis_flags var (atom)
image objects
HUD / screen objects
Default value:
Empty list.

This list is the opposite of the vis_contents list. If this atom is in any other atoms' visual contents, those parent atoms will appear in this list.

Because only turfs, objs, and mobs can be in visual contents, this var belongs only to those types.

Being in a visual locs list does not count as a reference, the same way that being a movable's loc does not count as a reference. If an object in this list otherwise runs out of references, it will be garbage collected and therefore removed from this list.


x var (atom)

See also:
loc var (atom)
Default value:
The x coordinate of the object on the map.

You may assign the coordinates of movable objects (mobs and objs), but this is not advisable. It is better to compute the new location (with locate()) and move them to that. Then you can use the normal Move() procedure, which enables all the normal movement behavior.

For areas that are on the map, this is the coordinate of the turf with the lowest z, y, and x coordinate (in that order) that is contained by the area.


y var (atom)

See also:
loc var (atom)
Default value:
The y coordinate of the object on the map.

You may assign the coordinates of movable objects (mobs and objs), but this is not advisable. It is better to compute the new location (with locate()) and move them to that. Then you can use the normal Move() procedure, which enables all the normal movement behavior.

For areas that are on the map, this is the coordinate of the turf with the lowest z, y, and x coordinate (in that order) that is contained by the area.


z var (atom)

See also:
layer var (atom)
loc var (atom)
Default value:
The z coordinate of the object on the map.

The z coordinate is how objects move between maps. When you include several maps in a project, they are placed on different z levels so that the full map is a single 3-dimensional space. It is also possible for a single map file to contain multiple z levels.

Do not confuse this with drawing layer. The z coordinate moves an object between different maps. The layer variable determines the order in which an object is drawn graphically relative to other objects at the same position on the map.

You may assign the coordinates of movable objects (mobs and objs), but this is not advisable. It is better to compute the new location (with locate()) and move them to that. Then you can use the normal Move() procedure, which enables all the normal movement behavior.

For areas that are on the map, this is the coordinate of the turf with the lowest z, y, and x coordinate (in that order) that is contained by the area.


client

See also:
client var (mob)
key var (mob)
procs (client)
vars (client)

Each connected player has a corresponding client object. It has variables and procedures which control aspects of player input/output. This object is also responsible for linking the player up to a mob.

The client can be reassigned from its original mob M to a new mob N by setting N.client = M.client. This process disconnects the player from M (calling M.Logout()) and connects the player to N (calling N.Login()). Setting the mob's key has the same effect.

Additional vars, procs, and verbs may be added to the client in order to give the player properties that are independent of the mob.


procs (client)

Built-in client procs:

client/proc
AllowUpload
Center
CheckPassport
Click
Command
DblClick
Del
East
Export
GetAPI proc
Import
IsByondMember
MeasureText
MouseDown
MouseDrag
MouseDrop
MouseEntered
MouseExited
MouseMove
MouseUp
MouseWheel
Move
New
North
Northeast
Northwest
RenderIcon
SendPage
SetAPI proc
SoundQuery
South
Southeast
Southwest
Stat
Topic
West

AllowUpload proc (client)

See also:
input proc
Format:
AllowUpload(filename, filelength)
When:
Called when the player attempts to upload a file to the server, through input() or a command.
Default action:
Allows the upload by returning 1.

The client who owns this proc (src) is the one trying to upload the file. If this proc returns a true value, the upload will be allowed. Otherwise, it will be rejected.

Example:

client AllowUpload(filename, filelength) if(filelength >= 524288) // 512K (0.5M) src << "[filename] is too big to upload!" return 0 return 1

Center proc (client)

See also:
walk proc
Format:
Center()
When:
Called when the player presses the "center" key or cursor.
Default action:
Cancels any automated movement by calling walk(usr,0).

CheckPassport proc (client)

See also:
IsSubscribed proc (world)
IsByondMember proc (client)
GetAPI proc (client)
SetAPI proc (client)
Format:
CheckPassport(passport_identifier)
Args:
passport_identifier: a text string assigned to you by the BYOND hub (or an ID/token for a different API; see below).

This built-in procedure checks to see if the user is subscribed to a particular BYOND hub entry. If the user is subscribed, the result is the number of days left (rounded up) on their subscription, or -1 for lifetime subscribers.

Example:

world hub = "My.Hub" //change this to your own hub entry mob/var full_access mob/Login() if(client.CheckPassport("0123456789abcdef")) full_access = 1 else src << "For full access, <a href=\ 'http://www.byond.com/hub/[world.hub]' >subscribe</a>!" return ..()

Note that in general the value of world.hub has nothing to do with the passport you happen to check. This example assumes the passport number belongs to world.hub just for the purpose of forwarding the user to the appropriate subscription page.

Other APIs

You can use this with other APIs that are supported by BYOND, which currently only applies to Steam and only if the game is specially built for Steam support.

To check ownership of a Steam game or DLC (must be the current game's ID or one of its DLCs), use "steam:NNNNNN" for the passport string, where NNNNNN is a Steam app ID. Note that the user must be logged into Steam for this to work.


Click proc (client)

See also:
Click proc (atom)
DblClick proc (client)
MouseDown proc (client)
MouseDrag proc (client)
MouseDrop proc (client)
MouseEntered proc (client)
MouseExited proc (client)
MouseMove proc (client)
MouseUp proc (client)
MouseWheel proc (client)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
show_popup_menus var (client)
Format:
Click(object,location,control,params)
When:
Called when the player clicks on the map or in the stat panels.
Args:
object: the object clicked
location: the client stat panel, location (turf) of object on map, grid cell, or other control-specific info
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.Click(location,control,params).

Example:

client Click(O) usr << "You clicked [O]" ..() // do default action

Note that due to network lag, it is possible when clicking on moving objects for the location of those objects to have changed by the time the Click() proc is executed. That is the reason for the location argument. It tells you where the click originally took place.

The argument format for this verb is:

Click(object as null|atom in usr.client,\ location as null|turf|text in usr.client,\ control as text, params as text)

Command proc (client)

Format:
Command(command as command_text)
When:
Called when the player types in something that is not understood as a valid command, or if the player is connected via telnet.
Default action:
None.

If this proc is used, players will be able to connect to your world via telnet. All telnet users' commands are routed through this proc instead of being parsed into verbs. Players who join the world through Dream Seeker will have their commands parsed as verbs first, and those commands will end up here only if there is no applicable verb.

Note that text received by this proc is not interpreted beforehand, so quotes " and backslashes \ should come through unaltered.

This proc is primarily useful if you want to handle parsing yourself (like for a MUD), or if your world is a chat server and verbs are not used much.


DblClick proc (client)

See also:
Click proc (client)
DblClick proc (atom)
MouseDown proc (client)
MouseDrag proc (client)
MouseDrop proc (client)
MouseEntered proc (client)
MouseExited proc (client)
MouseMove proc (client)
MouseUp proc (client)
MouseWheel proc (client)
mouse_opacity var (atom)
mouse_over_pointer var (atom)
show_popup_menus var (client)
Format:
DblClick(object,location,control,params)
When:
Called when the player double-clicks on the map or in the stat panels.
Args:
object: the object double-clicked
location: the client stat panel, location (turf) of object on map, grid cell, or other control-specific info
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.DblClick(location,control,params).

Example:

client DblClick(O) usr << "You double-clicked [O]" ..() // do default action

Note that due to network lag, it is possible when clicking on moving objects for the location of those objects to have changed by the time the DblClick() proc is executed. That is the reason for the location argument. It tells you where the click originally took place.

DblClick(object as null|atom in usr.client,\ location as null|turf|text in usr.client,\ control as text, params as text)

Del proc (client)

See also:
Logout proc (mob)
Format:
Del()
When:
Called when the player disconnects from the world.
Default action:
If the player is connected to a mob, call mob.Logout() to disconnect. If the player's connection to the world is still not dead, kill it.

Note that this does not automatically delete the player's mob. If you want to do that, you could do so in mob.Logout().


East proc (client)

See also:
Move proc (client)
Format:
East()
Returns:
1 on success; 0 on failure.
When:
Called when the player presses the "right" key or cursor.
Default action:
Calls src.Move() towards the east.

Export proc (client)

See also:
Import proc (client)
New proc (client)
hub var (world)
savefile
Format:
client.Export(file)
Args:
file: file to send to client

This stores the file on the user's computer in a special location unique to each registered world.hub setting. This is most useful for writing a client-side savefile, but any type of file may be stored. The purpose of this is to exchange information between different worlds running under the same hub path.

When a file is exported to the player's computer, it replaces any previous file stored by a game with the same world.hub value. This should not be used for anything requiring high security, because any other world could make use of the same hub path and access the file. It is also possible for the user to tinker with the file, since it resides on their computer.

To delete the client-side file completely, call client.Export() with no argument at all.

Example:

mob/verb/save() var/savefile/F = new() F << usr //write the player's mob usr.client.Export(F) client/New() var/client_file = Import() if(client_file) var/savefile/F = new(client_file) //open it as a savefile F >> usr //read the player's mob return ..()

GetAPI proc (client)

See also:
SetAPI proc (client)
CheckPassport proc (client)
Format:
GetAPI(Api, Name)
Args:
Api: the name of the API (e.g. "steam")
Key: the name of the value to read

Interfaces with supported external APIs to read information. Currently this only has meaning for Steam, for specially built games that have a Steam app ID.

This proc returns null any time the call or its results are invalid: for instance, trying to query a Steam stat from a user who isn't logged into Steam.

KeyReturn typeDescription
"steam" API
Requires that the server and client are using a valid Steam app ID, such as when a game is built for standalone distribution.
idtextReturns the user's numeric Steam ID, if any. Because this number is too big to fit in BYOND's numbering system, it is returned as text.
nametextReturns the user's persona name on Steam.
stat:NamenumReturns the value of the stat called Name.
achievement:NamenumReturns the date (for use with time2text) the achievement called Name, or 0 if it hasn't been earned.
achievement-data:NamelistReturns information about the achievement called Name. The result is an associative list with named values name (display name), desc (description), and optionally hidden and icon. (This call is the same no matter which client you call it for.)
achievementslistReturns a list of all possible achievements. Each item in the list is the internal name of the achievement, and it is associated with a list in the form described for achievement-data:Name. (This call is the same no matter which client you call it for.)

Import proc (client)

See also:
Export proc (client)
New proc (client)
savefile
Format:
client.Import(Query)
Args:
Query: optional query parameters

When no query parameters are given, this returns the client-side file last exported with client.Export(). This comes as an entry in the resource cache, which can be opened as a savefile among other things. If there is no file, null is returned. For an example, see client.Export.

When there are query parameters, these may be used to import a file from some alternate source. Currently this is not supported.


IsByondMember proc (client)

Format:
IsByondMember()
Args:
None.

This built-in procedure checks to see if the user is a BYOND Member. Use it to give special in-game rewards to those who support BYOND.

If the user is a Member, the result is the number of days left (rounded up) on their Membership, or -1 for lifetime Members.

Example:

mob/var special_features mob/Login() if(client.IsByondMember()) special_features = 1 else src << "For special features, <a href=\ 'http://members.byond.com/' >become a BYOND Member</a>!" return ..()

MeasureText proc (client)

See also:
maptext var (atom)
maptext_width var (atom)
maptext_height var (atom)
Format:
MeasureText(text, style, width=0)
Args:
text: The text to be measured
style: Stylesheet to be used (leave blank to use the default map control's styles, if any)
width: Width limit, if you only want to measure height; 0 means no limit
Returns:
A size value in "[width]x[height]" format, e.g. "60x16"

Because maptext rendering may vary by client, MeasureText lets you get a measurement of how text will be laid out, so you can adjust maptext_width and maptext_height accordingly.


MouseDown proc (client)

See also:
Click proc (client)
DblClick proc (client)
MouseDown proc (atom)
MouseDrag proc (client)
MouseDrop proc (client)
MouseEntered proc (client)
MouseExited proc (client)
MouseMove proc (client)
MouseUp proc (client)
MouseWheel proc (client)
mouse_opacity var (atom)
mouse_pointer_icon var (client)
show_popup_menus var (client)
Format:
MouseDown(object,location,control,params)
Args:
object: the object under the mouse pointer
location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.MouseDown(location,control,params).

This is called when the a mouse button is pressed while pointing to the object. Note that MouseUp() will always be called after MouseDown() is called, even if over empty space. That means object and location may be null.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through Click(), DblClick(), and MouseDrop(). The other procedures are simply available for completeness.

The argument format for this verb is:

MouseDown(object as null|atom in usr.client,\ location as null|turf|text in usr.client,\ control as text, params as text)

Note: In BYOND 3.5 this procedure took three different arguments: location, icon_x, and icon_y. Since icon_x and icon_y have been replaced, old code will need to be modified. Games compiled before this change will still work normally.


MouseDrag proc (client)

See also:
Click proc (client)
DblClick proc (client)
MouseDown proc (client)
MouseDrag proc (atom)
MouseDrop proc (client)
MouseEntered proc (client)
MouseExited proc (client)
MouseMove proc (client)
MouseUp proc (client)
MouseWheel proc (client)
mouse_pointer_icon var (client)
show_popup_menus var (client)
Format:
MouseDrag(src_object,over_object,src_location,over_location,src_control,over_control,params)
Args:
src_object: the object being dragged
over_object: the object under the mouse pointer
src_location: the turf, stat panel, grid cell, etc. from where the src object was dragged
over_location: the turf, stat panel, grid cell, etc. containing the object under the mouse pointer
src_control: The id of the skin control the object was dragged from
over_control: The id of the skin control the object was dragged over
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.MouseDrag(over_object,src_location,over_location,src_control,over_control,params).

This is called while dragging an object by pressing and holding the left mouse button over the object and moving the mouse. The over_object may be null if dragging over a stat panel or over other empty space.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through Click(), DblClick(), and MouseDrop(). The other procedures are simply available for completeness.

The argument format for this verb is:

MouseDrag(src_object as null|atom in usr.client,\ over_object as null|atom in usr.client,\ src_location as null|turf|text in usr.client,\ over_location as null|turf|text in usr.client,\ src_control as text, over_control as text, params as text)

MouseDrop proc (client)

See also:
Click proc (client)
DblClick proc (client)
MouseDown proc (client)
MouseDrag proc (client)
MouseDrop proc (atom)
MouseEntered proc (client)
MouseExited proc (client)
MouseMove proc (client)
MouseUp proc (client)
MouseWheel proc (client)
mouse_pointer_icon var (client)
show_popup_menus var (client)
Format:
MouseDrop(src_object,over_object,src_location,over_location,src_control,over_control,params)
Args:
src_object: the object being dropped
over_object: the object under the mouse pointer
src_location: the turf, stat panel, grid cell, etc. from where the src object was dragged
over_location: the turf, stat panel, grid cell, etc. containing the object under the mouse pointer
src_control: The id of the skin control the object was dragged from
over_control: The id of the skin control the object was dropped onto
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.MouseDrop(over_object,src_location,over_location,src_control,over_control,params).

This is called when a mouse button is released after dragging an object. The over_object may be null if dropping over a stat panel or over other empty space.

The argument format for this verb is:

MouseDrag(src_object as null|atom in usr.client,\ over_object as null|atom in usr.client,\ src_location as null|turf|text in usr.client,\ over_location as null|turf|text in usr.client,\ src_control as text, over_control as text, params as text)

MouseEntered proc (client)

See also:
Click proc (client)
DblClick proc (client)
MouseDrag proc (client)
MouseDrop proc (client)
MouseEntered proc (atom)
MouseExited proc (client)
MouseMove proc (client)
MouseUp proc (client)
MouseWheel proc (client)
mouse_opacity var (atom)
mouse_pointer_icon var (client)
show_popup_menus var (client)
Format:
MouseEntered(object,location,control,params)
Args:
object: the object under the mouse pointer
location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.MouseEntered(location,control,params).

This is called when no mouse buttons are pressed while pointing to the object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

The argument format for this verb is:

MouseEntered(object as null|atom in usr.client,\ location as null|turf|text in usr.client,\ control as text, params as text)

MouseExited proc (client)

See also:
Click proc (client)
DblClick proc (client)
MouseDrag proc (client)
MouseDrop proc (client)
MouseEntered proc (client)
MouseExited proc (atom)
MouseMove proc (client)
MouseUp proc (client)
MouseWheel proc (client)
mouse_opacity var (atom)
mouse_pointer_icon var (client)
show_popup_menus var (client)
Format:
MouseExited(object,location,control,params)
Args:
object: the object under the mouse pointer
location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.MouseExited(location,control,params).

This is called when the mouse moves off of an object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

The argument format for this verb is:

MouseExited(object as null|atom in usr.client,\ location as null|turf|text in usr.client,\ control as text, params as text)

MouseMove proc (client)

See also:
Click proc (client)
DblClick proc (client)
MouseDrag proc (client)
MouseDrop proc (client)
MouseEntered proc (client)
MouseExited proc (client)
MouseMove proc (atom)
MouseUp proc (client)
MouseWheel proc (client)
mouse_opacity var (atom)
mouse_pointer_icon var (client)
show_popup_menus var (client)
Format:
MouseMove(object,location,control,params)
Args:
object: the object under the mouse pointer
location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.MouseMove(location,control,params).

This is called when no mouse buttons are pressed while pointing to the object, and the mouse has moved. The first time the mouse moves over the object, MouseEntered() is called instead.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Defining it on only the objects that require it reduces overhead.

The argument format for this verb is:

MouseMove(object as null|atom in usr.client,\ location as null|turf|text in usr.client,\ control as text, params as text)

MouseUp proc (client)

See also:
Click proc (client)
DblClick proc (client)
MouseDown proc (client)
MouseDrag proc (client)
MouseDrop proc (client)
MouseEntered proc (client)
MouseExited proc (client)
MouseMove proc (client)
MouseUp proc (atom)
MouseWheel proc (client)
mouse_opacity var (atom)
mouse_pointer_icon var (client)
show_popup_menus var (client)
Format:
MouseUp(object,location,control,params)
Args:
object: the object under the mouse pointer
location: the turf, stat panel, grid cell, etc. containing the object where it was clicked
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.MouseUp(location,control,params).

This is called when a mouse button is released while pointing to an object.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. Most operations can be done through Click(), DblClick(), and MouseDrop(). The other procedures are simply available for completeness.

The argument format for this verb is:

MouseUp(object as null|atom in usr.client,\ location as null|turf|text in usr.client,\ control as text, params as text)

Note: In BYOND 3.5 this procedure took three different arguments: location, icon_x, and icon_y. Since icon_x and icon_y have been replaced, old code will need to be modified. Games compiled before this change will still work normally.


MouseWheel proc (client)

See also:
Click proc (client)
DblClick proc (client)
MouseDown proc (client)
MouseDrag proc (client)
MouseDrop proc (client)
MouseEntered proc (client)
MouseExited proc (client)
MouseMove proc (client)
MouseUp proc (client)
MouseWheel proc (atom)
mouse_opacity var (atom)
mouse_pointer_icon var (client)
Format:
MouseWheel(object,delta_x,delta_y,location,control,params)
Args:
object: the object under the mouse pointer
delta_x,delta_y: amount of wheel movement
location: the turf, stat panel, grid cell, etc. containing the object
control: the name of the skin control involved
params: other parameters including mouse/keyboard flags, icon offsets, etc.; see mouse handling
Default action:
Call object.MouseWheel(delta_x,delta_y,location,control,params).

This is called when the mouse wheel is moved while over an object or control. It is NOT called if over a browser control, or any control that is currently scrollable.

Positive values of delta_x and delta_y refer to scrolling right or up, respectively. Negative values are left and down, respectively.

Don't define this unless you need it, because it generates extra communication that is otherwise avoided. If you only need wheel support on specific objects, use atom.MouseWheel() instead which is more selective.

The argument format for this verb is:

MouseWheel(object as null|atom in usr.client,\ delta_x as num, delta_y as num,\ location as null|turf|text in usr.client,\ control as text, params as text)

Move proc (client)

See also:
East proc (client)
Move proc (movable atom)
North proc (client)
Northeast proc (client)
Northwest proc (client)
South proc (client)
Southeast proc (client)
Southwest proc (client)
West proc (client)
Format:
Move(loc,dir)
Returns:
1 on success; 0 on failure
When:
Called by the direction procs.
Default action:
Calls src.mob.Move(). Also cancels any automated movement by calling walk(usr,0).

New proc (client)

See also:
Export proc (client)
Import proc (client)
Login proc (mob)
New proc (datum)
Topic proc (client)
mob var (world)
savefile
Format:
New(TopicData)
Returns:
The newly connected mob, client.mob, or null to disallow the connection.
When:
Called when the player first tries to connect to the world.
Args:
usr: The mob in the world with the same key as the player, if it exists.
TopicData: If the player accessed the world with a "connection topic", this is the topic text. Otherwise it is null.
Default action:
Look for an existing mob with the same key as the player. If found, connect the player to that mob (mob.Login()). Otherwise, look for a prototype mob with the same key as the player. If found, create a mob of that type and connect the player to it. Otherwise, create a mob of type world.mob, give it the same name and gender as the player's key, and connect the player to it. If TopicData is not null, call client.Topic(TopicData). Finally, the player's mob is returned.

This is a fairly low-level procedure that you would only want to override if you cannot accomplish the same thing in mob/Login() or mob/New(). One reason to override client/New() is if player mobs are created from a savefile. In that case, you don't need a temporary mob to be created first.

Example:

client/New() if(usr) return ..() //reconnecting to existing mob else var/player_sav = "players/[ckey].sav" if(length(file(player_sav))) //if player savefile exists var/savefile/F = new(player_sav) //open it F >> usr //create saved mob return ..() //creates a new mob if necessary mob/Logout() var/player_sav = "players/[ckey].sav" var/savefile/F = new(player_sav) F << src del src

If you want to do any user-interaction before loading the saved mob, you will have to create a temporary mob first in order to interact with the player. In that case, you are better off doing things in mob/Login(), rather than client/New().

Note that for the above example to work, you must make proper use of the tmp flag when defining new object variables. Otherwise, this can end up sucking large portions of your world into each player savefile, which can have all sorts of unexpected consequences!


North proc (client)

See also:
Move proc (client)
Format:
North()
Returns:
1 on success; 0 on failure.
When:
Called when the player presses the "up" key or cursor.
Default action:
Calls src.Move() towards the north.

Northeast proc (client)

See also:
Move proc (client)
Format:
Northeast()
Returns:
1 on success; 0 on failure.
When:
Called when the player presses the "up-right" key or cursor.
Default action:
Calls src.Move() towards the northeast.

Northwest proc (client)

See also:
Move proc (client)
Format:
Northwest()
Returns:
Returns 1 on success; 0 on failure.
When:
Called when the player presses the "up-left" key or cursor.
Default action:
Calls src.Move() towards the northwest.

RenderIcon proc (client)

See also:
vis_contents var (atom)
Filter effects
Format:
RenderIcon(object)
Args:
object: An atom or appearance to render.
Returns:
A single-image icon file in which the object is rendered with all its overlays, visual contents, etc.

Use this proc to render an atom or an appearance as a single icon. This is a client proc because the server is not capable of rendering anything on its own.

Any overlays, image objects known to this client that are attached to the object, visual contents, maptext, and so on will be included in the render. The returned icon is sized to fit all of the above, and to include room for any expansion due to filter effects.

Example:

mob/proc/GetFlatIcon() return client?.RenderIcon(src)

Important notes regarding this proc:


SendPage proc (client)

Format:
SendPage(msg,recipient,options)
Returns:
Returns number of recipients successfully contacted.
Args:
msg: text to send
recipient: key or list of keys to page
options: text string containing key=value options

The user is prompted to authorize sending of the pager message. The recipient may easily respond or jump to the sender's location by clicking on the link in the pager message. The effect is identical to that of the sending a page through the Dream Seeker pager.

The options are encoded in the same format read by text2params(). The valid options are:

summon (0/1)
If not included in the options, this is 0. If included in the options without assigning it to anything, it is 1. A value of 1 sends the recipient the sender's location so they can join by clicking on the message.
email (0/1)
If not included in the options, this is 0. If included in the options without assigning it to anything, it is 1. A value of 1 sends causes the message to be delivered as email. If this is not possible, it is delivered as a long-lived pager message. Normally, pager messages expire within a short time after being sent (half an hour).
subject
For email messages, this specifies the subject to use.

SetAPI proc (client)

See also:
GetAPI proc (client)
CheckPassport proc (client)
Format:
SetAPI(Api, Key, Value)
Args:
Api: the name of the API (e.g. "steam")
Key: the name of the value to change
Value: the new value to set

Interfaces with supported external APIs to write information. Currently this only has meaning for Steam, for specially built games that have a Steam app ID.

This proc returns null any time the call or its results are invalid.

KeyReturn typeDescription
"steam" API
Requires that the server and client are using a valid Steam app ID, such as when a game is built for standalone distribution.
stat:NamenumChanges the value of the stat called Name. Returns 1 on success. This may fail if the stat change is too much or is out of range.
achievement:NamenumEarns the achievement called Name, or clears it. Value is expected to be a number, or number in text form, where 0 will clear the achievement and 1 will earn it.

SoundQuery proc (client)

See also:
/sound datum
sound proc
Format:
SoundQuery()
Args:
none
Returns:
A list of /sound datums with information about currently playing sounds.

This proc is used to ask a client about sounds that are playing. The /sound datums in the returned list have the following vars set:

Not all info about the sounds is retrieved, such as volume, frequency, etc. If those are needed, it should be a simple matter to keep track of them in your code. The main purpose of SoundQuery() is to ascertain the current status of playing sounds.


South proc (client)

See also:
Move proc (client)
Format:
South()
Returns:
Returns 1 on success; 0 on failure.
When:
Called when the player presses the "down" key or cursor.
Default action:
Calls src.Move() towards the south.

Southeast proc (client)

See also:
Move proc (client)
Format:
Southeast()
Returns:
1 on success; 0 on failure.
When:
Called when the player presses the "down-right" key or cursor.
Default action:
Calls src.Move() towards the southeast.

Southwest proc (client)

See also:
Move proc (client)
Format:
Southwest()
Returns:
Returns 1 on success; 0 on failure.
When:
Called when the player presses the "down-left" key or cursor.
Default action:
Calls src.Move() towards the southwest.

Stat proc (client)

See also:
Stat proc (atom)
stat proc
statobj var (client)
statpanel proc
statpanel var (client)
Info control (skin)
Format:
Stat()
When:
Called periodically by the client to update the stat window.
Default action:
Call statobj.Stat().

If this procedure sleeps (or engages in some other waiting operation), it will not be called again until it finally returns. This allows you to effectively decrease the frequency of calls to the proc. You might want to do that if it is a fairly lengthy procedure, and frequent calls are slowing things down.

To increase the frequency of stat updates, you can lower world.tick_lag.

Note: Typically only the currently viewed statpanel is updated, which saves on some network activity and a little time. If however the proc sleeps, you need to be sure that any pending updates are displayed once the right panel is available. Therefore if you're resetting a var that indicates the proc should sleep next time, it should not be reset unless you know the player is looking at the right statpanel and has received the updates.

Example

client/var/updategold = 1 // set to 1 if gold changes client/var/updateinventory = 1 // set to 1 if inventory changes client/Stat() // if not ready to update, Stat() won't be called again till sleep is done while(!updategold && !updateinventory) sleep(5) if(statpanel("Gold")) // switch to Gold panel and ask if player is looking at it stat("Gold", mob.gold) updategold = 0 // we updated, so turn this flag back off if(statpanel("Inventory")) stat(mob.contents) updateinventory = 0

Because sleeping in Stat() requires more thinking through, it's best to do so only in cases where Stat() has to do a lot of intensive calculations.


Topic proc (client)

See also:
New proc (client)
Topic proc (datum)
link proc
ref text macro
Format:
Topic(href,href_list[],hsrc)
When:
Called when a player connects to a world with a "connection topic" or when the player runs a hyperlink in the current world by clicking one embedded in text or generated by the link() instruction.
Args:
href: The topic text (everything after the '?' in the full href).
href_list: List of key/value pairs in href (produced from params2list(href)).
hsrc: The object referenced by the "src" parameter in href or null if none.
Default action:
Call the hsrc object's own Topic() proc.

The following example uses a very simple href value.

Example:

mob/Login() src << "Click <a href=?source>here</a> to download the source code." return ..() client/Topic(href) if(href == "source") usr << file("world.dm") usr << file("world.rsc") else ..()

Be sure to call the default handler unless you want to prevent rerouting of topics to other objects.

Always validate the input in Topic() calls to make sure it's correct and the query you're recieving is legitimate. For security reasons, you will probably want to control which objects a player has access to, since a player could spoof a topic link containing any arbitrary object reference. (Never trust those sneaky players!)

The next example demonstrates an href that gets handled by another object. This is how you would normally want to do things. It is best not to override client/Topic() (as in the example above) unless you need to intervene in the low-level details of routing the request to the right object.

You specify the object that will handle the request by using a parameter called "src".

Example:

mob/Login() src << "Click <a href='?src=\ref[src];action=startgame'>here</a> to start." return ..() mob/Topic(href,href_list[]) switch(href_list["action"]) if("startgame") usr << "Starting game..." else return ..()

Although it is slightly more complex, the use of the parameter list allows you to easily include extra data and new functionality. Just remember that the data in the list is always stored as text, so if you are expecting a number or an object, you must convert it yourself (with text2num(), locate(), or whatever).


West proc (client)

See also:
Move proc (client)
Format:
West()
Returns:
Returns 1 on success; 0 on failure.
When:
Called when the player presses the "left" key or cursor.
Default action:
Calls src.Move() towards the west.

vars (client)

Built-in client vars:

client/var
address
authenticate
bounds
byond_build
byond_version
CGI
ckey
color
command_text
connection
control_freak
computer_id
default_verb_category
dir
edge_limit
eye
fps
gender
glide_size
images
inactivity
key
lazy_eye
mob
mouse_pointer_icon
perspective
pixel_x
pixel_y
pixel_w
pixel_z
preload_rsc
screen
script
show_map
show_popup_menus var
show_verb_panel
statobj
statpanel
tick_lag
timezone
verbs
view
virtual_eye

CGI var (client)

In CGI mode, DreamDaemon is normally being executed by a web server and accessed by a web browser. The CGI object is an add-on to the basic client object for handling this case.

The CGI object is defined and documented in a separate code library html/CGI.dm. You can find the current version at www.byond.com.


address var (client)

Default value:
The network address of the player's client.

This is a read-only value which contains the player's network address.


authenticate var (client)

This value may be set to 0 at compile-time to disable BYOND hub-based authentication of users. The default value is 1, which enables authentication. Hub authentication provides an additional level of assurance that the user is really the owner of the BYOND key in question.

When a world requests certification, Dream Seeker generates a random password and passes it through the hub (for certification) to the world. The certificate is saved for faster access in the future and for protection against possible hub outages.

Some applications do not depend on the validity of the user's identity. In that case, it would be more efficient to turn off the extra level of authentication. In other situations, the hub may not be available, such as from behind a firewall or on a LAN without internet access. In those cases, all hub access (including authentication) can be disabled by entering the command ".configuration hub-address none" in Dream Seeker.

Connections to worlds on the same machine are not hub-authenticated to allow for convenient offline testing.


bounds var (client)

(Also bound_x, bound_y, bound_width, and bound_height.)
See also:
bounds proc

The read-only bounds var returns the map coordinates, in pixels, covered by the client's viewport when accounting for pixel offsets, eye, step, etc. (The coordinates are only relevant to the default client.dir value of NORTH, and the TOPDOWN_MAP or SIDE_MAP map formats.)

If the viewport is not currently on the map (for instance, when the eye is at a null location), the var reads as null. Otherwise, it is a list with five values (x, y, width, height, z) in the same form used by the bounds proc.

The alias vars bound_x, bound_y, bound_width, and bound_height can also be used to retrieve the individual values from the list. They too will be null if the viewport is not on the map.


byond_build var (client)

See also:
DM_VERSION macro
byond_version var (client)
byond_version var (world)

This is the build number (minor version) of BYOND being run by this client. Typically this is not useful information, but it can come in handy when diagnosing issues reported by players using a beta build.

Clients running versions of BYOND prior to 512 (major version) will not have this information. It is also not guaranteed to exist for non-Dream Seeker connections. When not available, byond_build is 0.


byond_version var (client)

See also:
DM_VERSION macro
byond_build var (client)
byond_version var (world)
system_type var (world)

This is the version of BYOND being run by this client. A game designed to work around known bugs in older versions could use this to adapt its behavior accordingly. It is also possible to prevent players with much older versions from joining the game.


ckey var (client)

See also:
ckey proc
key var (client)

This is a read-only value that is the canonical form of the player's key (ie the value returned by ckey()). Among other things, this could be used as a unique directory name in a server-side save file for storing player information. See the ckey() proc for an example.


color var (client)

See also:
color var (atom)
appearance_flags var (atom)

Casts a color multiplication or matrix effect over the entire main map. This behaves exactly the same as atom.color, and will be combined with atom.color (which comes first) where present. See atom.color for more information.

If a matrix is used, the alpha column and row will have no effect.

Icons that have the NO_CLIENT_COLOR value in appearance_flags will not be subject to client.color. This can be useful for HUD objects.

This value can be animated.

Example:

mob/proc/DayNight(is_day) if(client) client.color = is_day ? \ null : \ list(0.2,0.05,0.05, 0.1,0.3,0.2, 0.1,0.1,0.4)

command_text (client)

See also:
arguments (verb)
command parameter
macros (client script)
Input control (skin)
command parameter (skin)
macros (skin)
Default value:
null

Note: In BYOND 4.0 this var is deprecated. The command parameter for an Input control can be set to !command (! in front of your default command) which does the same thing.

This text is placed onto the command line, to be followed by whatever the user may type. It is usually the name of a verb followed by a space, such as "say ". The user can clear this and enter a different command by hitting backspace, escape, delete, or /.

Example:

client command_text = "say " verb/say(T as text) world << "[usr] says, '[T]'"

It is also possible to turn on macro mode, in which each keypress executes a keyboard macro, by setting command_text to ".alt ". That stands for the Alt key, which can be used to execute macros in normal mode.

This variable could also be used to create a specialized command prompt. For example, a traditional style MUD command-line could be implemented like this:

Example:

client command_text = "> " verb/command(C as command_text) set name = ">" usr << "Your command: [C]"

This example uses the command_text input type, which accepts raw text, with no quoting, escaping, or translating, so that you can invent whatever syntax you want.


computer_id var (client)

Default value:
A unique numerical identifier for the player's computer. The value is in text form.

This is a read-only text value which contains a unique numerical identifier for the player's computer. Its primary purpose is to detect if players are connecting to a server with multiple accounts on the same machine, while still allowing for multiple accounts on the same network (eg, through a router).


connection var (client)

This is a read-only var describing the type of client that is connected.

Possible values:
"seeker" - The player is connected through Dream Seeker
"telnet" - The player is connected through telnet
"world" - The client is actually a world.Export() connection from another server
"cgi" - The client is connected via CGI (irrelevant to most worlds)
"web" - The client is connected via the Web client
"http" - The client is an HTTP connection (used by the Web client's virtual server)

Other values may be supported in the future.

An empty value means the connection type is unknown because a full handshake hasn't been completed yet.


control_freak (client)

See also:
User interface skins
macros (skin)
macros (client script)
Default value:
0

This var lets you set flags to turn off options that are normally present for the end user. You can combine these flags with the | operator. The value 1 is equivalent to CONTROL_FREAK_ALL and will disable everything.

CONTROL_FREAK_ALL
If this value is used, it affects all the options below.
  • User-defined macros may not be used.
  • Only the world's skin or the default BYOND skin will be loaded, not a user-customized version.
  • The Options & Messages window in Dream Seeker is inaccessible. It will only come up while first connecting to a remotely hosted world, or if a world takes a long time to load. The .options command will not make it appear.
  • The menu items from Options & Messages are unavailable in Dream Seeker's system menu.
  • The default F2 macro for the .screenshot command is turned off. The command is then only accessible through the skin you create.
CONTROL_FREAK_SKIN
Toggles the ability to create a custom version of the skin.
CONTROL_FREAK_MACROS
Toggles the ability to use and define custom macros.

Using CONTROL_FREAK_ALL will default to disabling everything, and the other flags will reenable only the features you want. For example, CONTROL_FREAK_MACROS alone will disable the ability to use your own macros but nothing else. CONTROL_FREAK_ALL | CONTROL_FREAK_MACROS will disable everything except macros.

This value can be changed at runtime.

Note: If you define your own skin for the world, and disable the ability to use a custom skin or user-defined macros, you must be sure to define any macros your world may need. For instance, arrow keys may be needed for movement.


default_verb_category var (client)

See also:
category setting (verb)
show_verb_panel var (client)
Default value:
"Commands"

All verbs with category "" (the default value) are treated as though they had this category setting instead. In other words, this is the name of the panel that contains them. You could even turn that panel off by setting this value to null.


dir var (client)

Default value:
NORTH

This defines the relationship between the world's coordinate system and the player's screen. The default means that the player sees the map exactly as it was created (in the map-editor or at runtime). Changing it to one of the other directions causes the player to see the map as if it were rotated to that direction. This means that a player with client.dir = SOUTH would see the map inverted relative to a person with client.dir = NORTH. That's handy in two-player board games where you want both players to see their side in the same place.

Note that this does not turn icons upside down! The map is rotated, but the icons on the map remain in their normal orientation.

Movement keys are remapped so that a player with client.dir = SOUTH hitting the up arrow will generate a call to client.South() rather than the usual client.North().


edge_limit var (client)

See also:
eye var (client)
lazy_eye var (client)
perspective var (client)
view var (client)
screen_loc var (movable atoms)
Default value:
null

This value determines the limits that a client's eye will display. If client.perspective uses the EDGE_PERSPECTIVE flag, the view shouldn't scroll beyond the bounds set by edge_limit. If the bounds of edge_limit are as big as or smaller than the client's view, no scrolling will occur even if EDGE_PERSPECTIVE is not used. Normally this value is null, which provides freedom for the eye to move anywhere on the map. It may be changed to a text value describing the limits in more detail.

The format is similar to atom.screen_loc which uses "[x1],[y1] to [x2],[y2]". It can also use directions such as "SOUTHWEST to NORTHEAST", which refer to the limits of the map.

Example:

area/house var/x1,x2,y1,y2 Entered(mob/M) if(ismob(M) && M.client) M.client.edge_limit = "[x1],[y1] to [x2],[y2]" Exited(mob/M) if(ismob(M) && M.client) M.client.edge_limit = null

eye var (client)

See also:
edge_limit var (client)
lazy_eye var (client)
mob var (client)
perspective var (client)
glide_size var (client)
view var (client)
virtual_eye var (client)
view var (world)
step_x var (movable atom)
step_y var (movable atom)
Default value:
The connected mob, client.mob.

This value determines the center of the player's map. The default value simply means that the visible region is normally centered on the player's mob. Effects such as setting perspective to EDGE_PERSPECTIVE or using lazy_eye can move the map off-center temporarily. The eye is the ideal center, not necessarily the actual center; to find the actual center, use virtual_eye.

The eye's step_x/y vars, if present, are also used to allow smooth scrolling of the map. These also obey lazy_eye and edge_limit.

Note that the visibility of objects is still computed from the point of view of the mob rather than the eye. This allows the use of lazy_eye or similar effects that control the panning of the map while still having the player see only what the mob can see. To determine visibility from the eye, you can change the value of client.perspective.

If a player connects to a new mob M, client.eye automatically changes to M.

Example:

client eye = locate(5,5,1)

This fixes the center of the player's map at the turf coordinate (5,5,1). Since the eye is fixed, the map will not scroll even as the player's mob moves out of the visible range.


fps var (client)

See also:
fps var (world)
tick_lag var (client)
Pixel movement
Default value:
0 (uses world.fps value)

This is a client version of world.fps, so that the client can run at a faster speed for animations. For example, setting client.fps to 40 while world.fps is the default 10 will mean that all animations and glides are smoothed out and displayed at 40 FPS, even though the server still runs at 10 FPS. The result is a nicer-looking game with no additional impact on the server.

When this value is 0, the client and server tick at the same rate.


gender var (client)

See also:
New proc (client)
gender var (atom)
key var (client)
macros (text)

This is the client's gender, which is an attribute of the player's key. By default, when a new mob is made for a player (in client.New()), the new mob gets the same name and gender as the player's key. This influences text macros like \he, which may expand to "it", "he", "she", or "they". Valid values are:

"neuter" "male" "female" "plural"

glide_size var (client)

See also:
eye var (client)
glide_size var (movable atoms)
Default value:
0

Note: The way this setting is used depends on world.movement_mode. See Gliding for more details.

This controls the number of pixels the map is moved in each step during scrolling of the map. The default value of 0 chooses automated control over this value, which generally results in a minimum step of 4 pixels that is increased when necessary to keep up with motion of the map.

Be careful about using small step sizes. Icons with high contrast pixel-level detail can look pretty ugly when displaced by short distances.

This was renamed from pixel_step_size.


images var (client)

See also:
image objects
image proc

This is a list of images that are displayed to the user. The output operator is one way to add entries to this list. Deleting an image object will automatically remove it from the display, but if you want to retain an image (so other people can still see it), it can be removed by directly modifying this list.

Example:

var/image/I = new('image.dmi',usr) usr.client.images += I //display it sleep(50) usr.client.images -= I //remove it from the display Displaying the image can also be achieved like this: usr << I

inactivity var (client)

See also:
tick_lag var (world)

This is equal to the amount of time (in server ticks, which default to 1/10s) since the player's last action (such as executing a verb, moving, clicking an object, or selecting a topic link). This value is reset to 0 after each new action so you can use it to determine the time that has passed since the last one.

Example:

mob/verb/inactivity() usr << "You have been inactive for [client.inactivity/10] seconds."

key var (client)

See also:
key var (mob)
Default value:
The player's key identity.

This is a read-only value that contains the player's key. Once the player is attached to a mob M, M.key == M.client.key.


lazy_eye var (client)

See also:
view var (client)
view var (world)
Default value:
0

This is the maximum "lag" between client.eye and client.mob. The mob can stray up to this many tiles before the eye will move to keep it in view. The default value of 0 means that the eye always moves as the mob moves, keeping the mob at the center of the player's map.

Setting this value to a non-zero value automatically initializes client.eye to client.mob.loc (or to the center of the full map if that is possible). Thereafter, client.eye will stray from the mob as it moves about the map, making one big jump to catch up whenever the mob gets out of range.

Example:

client lazy_eye = 5

This setting allows client.mob to move onto the entire 11x11 visible region without changing the value of client.eye. The moment it steps out of this region, the entire region will shift 5 tiles in the direction of motion.

You can assign lazy_eye to any value valid as a view size, so, for example, if you have a non-square setting for client.view, say, "17x11", you could apply a similar setting to lazy_eye. You can even make one dimension lazy and the other one strictly centered: "0x5".


mob var (client)

Default value:
Determined in client.New(), by default world.mob.

This is the mob to which the client is connected. The client and its connected mob have the following symmetry:

client == mob.client client.mob == mob client.key == mob.key

mouse_pointer_icon var (client)

See also:
Click proc (client)
MouseDown proc (client)
MouseDrag proc (client)
MouseDrag proc (client)
MouseUp proc (client)
mouse_drag_pointer var (atom)
mouse_drag_pointer var (atom)
mouse_drop_zone var (atom)
mouse_over_pointer var (atom)
Default value:
null

This is an icon file (.dmi) containing custom mouse cursors to use in place of the standard ones. The different possible mouse states are distinguished by special icon state names:

""
Activated when over empty space or an object with mouse_over_pointer = MOUSE_INACTIVE_POINTER.
"over"
Activated when over an object with mouse_over_pointer = MOUSE_ACTIVE_POINTER.
"drag"
Activated when dragging an object with mouse_drag_pointer = MOUSE_ACTIVE_POINTER.
"drop"
Activated when dragging an object over with mouse_drop_pointer = MOUSE_ACTIVE_POINTER and the object underneath has mouse_drop_zone set.
"all"
Always activated, no matter what the state of the mouse.

perspective var (client)

See also:
eye var (client)
mob var (client)
Default value:
MOB_PERSPECTIVE
Possible values:
  • MOB_PERSPECTIVE
  • EYE_PERSPECTIVE
  • EDGE_PERSPECTIVE

This controls the eye's apparent center and what can be seen by the client.

EYE_PERSPECTIVE determines how visibility calculations are performed when client.eye and client.mob are different. Normally, visibility is done from the position of the mob, rather than from the eye (which is actually just the center of the map view). The alternative flag is MOB_PERSPECTIVE, the default.

EDGE_PERSPECTIVE limits scrolling to the bounds of the map (1,1 to world.maxx,world.maxy), and does not keep the mob centered if it strays near the edge.

The above values can be used together via the | operator.


pixel_x var (client)

See also:
glide_size var (client)
pixel_y var (client)
pixel_w var (client)
pixel_z var (client)
Default value:
0

This displaces the player's viewpoint on the x-axis by the specified number of pixels. Can be animated with the animate() proc.


pixel_y var (client)

See also:
glide_size var (client)
pixel_x var (client)
pixel_w var (client)
pixel_z var (client)
Default value:
0

This displaces the player's viewpoint on the y-axis by the specified number of pixels. Can be animated with the animate() proc.


pixel_w var (client)

See also:
glide_size var (client)
pixel_x var (client)
pixel_y var (client)
pixel_z var (client)
map_format var (world)
Default value:
0

This displaces the player's viewpoint horizontally by the specified number of pixels. This value is meant to be used when world.map_format is not set to a default top-down view. Can be animated with the animate() proc.


pixel_z var (client)

See also:
glide_size var (client)
pixel_x var (client)
pixel_y var (client)
pixel_w var (client)
map_format var (world)
Default value:
0

This displaces the player's viewpoint vertically by the specified number of pixels. This value is meant to be used when world.map_format is not set to a default top-down view. Can be animated with the animate() proc.


pixel_step_size var (client)

Renamed to glide_size.


preload_rsc var (client)

Default value:
1.

This variable controls whether resource files (icons and sounds) are automatically downloaded by Dream Seeker when first connecting, or whether they should be downloaded as needed. Resource files are cached (in byond.rsc) for future use, so this should only affect people who have not played the game before or who have not played it for some time.

The three possible settings are:

0
do not preload any resources
1
preload compiled-in resources only
2
preload all resources including those uploaded by players
URL
preload resources from specified file

Preloading resource files will eliminate delays later on, but may cause a very long initial delay when logging in.

Resources may also be distributed from a website to save bandwidth on the machine hosting the game. Simply zip up the .rsc file, upload it to a web site, and put the URL here.

Example:

client/preload_rsc = "http://dan.byond.com/mygame_rsc.zip"

Instead of putting the .rsc file in the .zip, you can also put the individual resource files there. This would allow you to select specific files that you would like to be preloaded. For example, you could create a different resource package for different parts of the game world and assign client.preload_rsc dynamically as the player moves into each different area.

Once Dream Seeker has downloaded a resource package, it caches it and will not download it again, even if you upload a new version of the file. This allows you to make small changes without forcing a complete refresh. Any files which are not found in the preload package are simply downloaded from the game server directly.

If you want to force a complete refresh, simply change the name of the resource package. For example, you could put a version number in the name of the file: mygame_rsc_01.zip, mygame_rsc_02.zip, and so on.


screen var (client)

See also:
HUD / screen objects
screen_loc var (movable atoms)

This is a list of objects that are displayed on the user's screen. The object's screen_loc variable controls where it appears (if it appears at all). This allows one to create the elements of a graphical user interface, with such features as buttons, drag/drop areas, and stat monitors.

Screen objects (visible or otherwise) may also be used to make verbs available to users. To make them accessible, define verbs on the screen object like this:

set src in usr.client.screen

script var (client)

See also:
#include directive
PASSWORD_TRIGGER (client script)
URL (client script)
aliases (client script)
browser configuration
command_text (client)
macros (client script)
macros (skin)
style sheets
style sheets (in scripts)
Default value:
none

Client scripts are mini-programs used to configure the client. The language they use is called DM Script, and will undoubtedly expand in the future. Currently, client scripts can be used to define style sheets, command aliases, and macros. When executed directly by a player, they can also be used to specify an initial URL to open and a password trigger (for some ancient telnet worlds that don't suppress password echo).

For the specific syntax of DM Script, see the relevant reference sections listed above.

The client.script variable may be assigned to script code in a text string (double quotes) or in a file (single quotes). You can also simply include the file in your project or explicitly use the #include statement. Files containing DM Script should have the extension .dms.

Example:

client/script = "<STYLE>BODY {font: monospace}</STYLE>"

This example selects a default monospace font for all output to the terminal.

In addition to scripts loaded via client.script, the player may have client-side scripts. These are either called connection scripts or post-connection scripts depending on whether they are used to automatically connect to a world or whether they are executed automatically after connecting to a world. In either case, the player's scripts are always executed before the designer's client.script script, so style sheets from the designer have higher precedence by default.

There are three post-connection client-side scripts for the three types of worlds the client can connect to: byond.dms, telnet.dms, and irc.dms. These are automatically executed if the player connects directly to a world without using a connection script to do so. The intention is to load any standard configurations such as style sheets and command aliases.


PASSWORD_TRIGGER (client script)

Format:
#define PASSWORD_TRIGGER "assword:"

This defines a special text trigger used to detect when the user is being prompted for a password in telnet mode. Most MUDs automatically suppress password echo, but if they do not, it is necessary to use this setting to hide it. Multiple triggers may be defined as necessary.

The example above is more robust than the more polite version because it works whether they capitalize the 'P' or not...


URL (client script)

Format:
#define URL "byond://byond.com:6000"

Defining a URL in a script, specifies the world to connect to when the script is executed by the player. This is referred to as a connection script, because the player uses it to connect to a world. Other post-connection scripts such as byond.dms or a script loaded through client.script are only used to configure the client after it has connected to a world. In those cases, the URL setting has no effect.

It is important to enclose the URL in double quotes. Otherwise, the // symbol would be mistaken for a comment.


browser configuration

See also:
URL (client script)

DM Script can be used to effectively make a hyperlink in a web document to a BYOND world. This is done by making a DM Script file that defines the desired URL. It need do nothing more than that. When a user clicks on the link in a web browser, DreamSeeker will pop up, execute the script, and connect to the specified URL.

Some browsers may need to be configured to know what to do with a DM Script file. For example, in Netscape, you can add an entry to the list of helper applications. You should add a MIME type called 'application/x-dms' with the description 'DM Script' and the extension dms. Have this execute DreamSeeker with the .dms file as an argument.

Example:

myworld.dms

/*If your browser shows you this, you either need to install BYOND (it's free!) from www.byond.com, or you need to configure your browser to execute DreamSeeker with DM Script (.dms) files. */ #define URL "byond://myworld"

myworld.html

<html> <head><title> Welcome to My World </title></head> <body> <p>You can connect to my world <a href=myworld.dms>here</a>. </body> </html>

aliases (client script)

See also:
macros (client script)
script var (client)
verbs

Command aliases have a syntax similar to verbs. They define a command and a series of arguments which can then be used to execute a new command. The most common use for this is in a telnet world like a MUD. By defining aliases corresponding to the MUD commands, the player can have primitive command expansion and help.

The syntax of an alias definition is best illustrated by the following example:

alias/say(msg as text) set desc = "speak your mind" return "say [msg]"

As you can see, it is just like a verb. Alias have all the same properties as verbs, except the src setting is always equal to the player.

The value returned by an alias is executed as a command. In telnet mode, the command to execute is often simply the same as the command that was entered (since the alias was only defined to provide command expansion and help). Since that is such a common case, the return value defaults to the alias name followed by each of the arguments. The example above, for instance, would have the same effect without an explicit return statement.

Note that commands executed via an alias are never interpreted as aliases. Otherwise, examples such as the one above would result in an infinite loop.


macros (client script)

See also:
macros (skin)
aliases (client script)
command_text (client)
script var (client)
verbs

Macros are just like aliases, except that they are triggered by a single key (or combination of keys) instead of a full command. When a macro is executed, it returns a text string which is then executed as a command. So a macro is just a short-cut for entering a command.

The following example illustrates the syntax for entering a typical set of macros.

Example;

macro ALT+I return "inventory" ALT+SHIFT+I return "inventory\nequipment" //multiple commands ALT+s return "say \..." //command to be edited

Note: In old versions of BYOND, character keys required the Alt key to be pressed to trigger the macro, and did not include "ALT+" to do so. This behavior has changed, and the name of the macro is just like the format used in skin files. You can now use a key name, and modifiers like SHIFT+, CTRL+, ALT+, +REP, and +UP. Old .dms and client.script files (prior to version 507) should be updated accordingly when recompiling in a newer version.


style sheets (in scripts)

See also:
script var (client)
style sheets

Style sheets may be included in DM Script by putting the style sheet inside the HTML tags <STYLE> and </STYLE>. In general, any text enclosed in start and end tags will be sent to the player's terminal, so you could use client.script to output a welcome message as well as loading a style sheet.

Example:

client/script = "<STYLE>BODY {background: black; color: aqua}</STYLE>"

This example style sheet makes the player's terminal have a black background and aqua colored text. When changing the background color, it is important to change the color of system and link text as well. See the section on style sheets for an example.


show_map var (client)

See also:
show_verb_panel var (client)
view var (client)
view var (world)
Default value:
1

This variable may be used to turn off the view of the map in Dream Seeker. This could be useful for making text MUDs where the rooms are turfs (ie most rooms can be laid out on a grid but you don't want the user interface to show the map in any way).

The following example shows one useful combination of settings. Note that setting world.view=-1 also disables the map, but it also sets the default value of the view() depth in such a way as to always return an empty list.

Example:

client show_map = 0 //Text is best! world view = 0 //You can interact only with objects in same turf. mob density = 0 //Allow multiple mobs in a room.

show_popup_menus var (client)

See also:
right-click parameter (skin)
Click proc (client)
DblClick proc (client)
MouseDown proc (client)
MouseDrag proc (client)
MouseDrop proc (client)
MouseEntered proc (client)
MouseExited proc (client)
MouseMove proc (client)
MouseUp proc (client)
Default value:
1

This variable may be used to turn off the popup "context" menus that are displayed by default when an object on the map or stat panels is right-clicked. If client.show_popup_menus==0, then right-clicks will instead be passed to the various mouse functions.


show_verb_panel var (client)

See also:
category setting (verb)
default_verb_category var (client)
show_map var (client)
Default value:
1

Setting this to 0 turns off the verb panel in Dream Seeker. You might want to do that, for instance, if you've only got one verb (like "say") and the panel looks stupid with just one verb in it.

Example:

client show_verb_panel = 0

statobj var (client)

See also:
Stat proc (client)
stat proc
statpanel proc
statpanel var (client)
Info control (skin)
Default value:
client.mob (the player's mob).

This value indicates which object the player currently has loaded in the stat panels.


statpanel var (client)

See also:
Stat proc (client)
stat proc
statobj var (client)
statpanel proc
Info control (skin)
Default value:
null

This value indicates which stat panel is currently visible to the player. You can assign it to force a different panel to become the top panel. The special value "verbs" activates the panel of commands.


tick_lag var (client)

See also:
tick_lag var (world)
fps var (client)
Pixel movement
Default value:
0 (uses world.tick_lag value)

This is a client version of world.tick_lag, so that the client can run at a faster speed for animations. For example, setting client.tick_lag to 0.25 while world.tick_lag is the default 1 will mean that all animations and glides are smoothed out and displayed at 40 FPS, even though the server still runs at 10 FPS. The result is a nicer-looking game with no additional impact on the server.

When this value is 0, the client and server tick at the same rate.


timezone var (client)

See also:
realtime var (world)
timeofday var (world)
timezone var (world)
time2text proc

This is the time offset from UTC, in hours, for the client's time zone. It can be used in the time2text() proc.


verbs list var (client)

See also:
list
Default value:
The list of verbs defined for the client.

This is a list of the client's verbs. Initially, it contains all of the verbs defined for the client. It may be used to add and remove verbs at runtime.


view var (client)

See also:
lazy_eye var (client)
show_map var (client)
view proc
view var (world)
Default value:
world.view (which is 5 by default)
Possible values:
-1 to 34 or "WIDTHxHEIGHT"

This controls the size of the map window in Dream Seeker. Normally, you would simply compile with world/view assigned to whatever you want, but in some cases, you might want to customize the map size for different players, such as admins or subscribed users.

Like all other view sizes in DM, this may either be a view depth or an absolute size. A view depth is a single number that determines how far from a center point the edges of a square viewable region extend. A value of 5 creates edges which are 2*5+1 = 11 tiles long.

The newer, more flexible syntax is a text string of the form "WIDTHxHEIGHT". For example, a view depth of 5 corresponds to "11x11". Using this syntax, you can create non-square views as well.

The maximum view size is about 5000 tiles, or roughly 70x70.


virtual_eye var (client)

See also:
edge_limit var (client)
eye var (client)
lazy_eye var (client)
mob var (client)
perspective var (client)
view var (client)
Default value:
client.eye

This value determines the actual center of the player's map display. It is based on client.eye and whenever possible matches it; however it may instead be a turf, or null, when the eye is off-center.

The value of virtual_eye is read-only.


database datum

See also:
database query datum
procs (database)
stddef.dm file

A /database datum gives you the ability to create or access a database using SQLite, which allows you to run complex database queries on any platform.

Creating a /database/query datum will let you put together a query, and once it's ready you can call its Execute() proc to run it.

SQLite databases in BYOND support numerical values (such as INTEGER or FLOAT), text (TEXT), and cache files such as icons (BLOB). Null values are also allowed.

Example:

var/database/db = new("mydb.db") var/database/query/q = new("SELECT * FROM my_table WHERE name=?", usr.key) if(q.Execute(db) && q.NextRow()) // returns a list such as list(name="MyName", score=123) return q.GetRowData() // no data found return null

procs (database)

See also:
database datum
database query datum
procs (database query)

Built-in database procs:

database/proc
Close
Error
ErrorMsg
New
Open

Close proc (database)

See also:
database datum
Open proc (database)
Format:
Close()

If a database is currently open, this will close the database and any queries currently running in it. Usually you don't need to call this directly, because deleting the datum will do it for you.


Error proc (database)

See also:
database datum
database query datum
ErrorMsg proc (database)
Format:
Error()

Returns the error code last received by the database.


ErrorMsg proc (database)

See also:
database datum
database query datum
Error proc (database)
Format:
ErrorMsg()

Returns the error message last received by the database.


Open proc (database)

See also:
database datum
Close proc (database)
New proc (database)
Format:
Open(filename)
Args:
filename: The database filename to open

Opens a database file. If another database was already open, it is closed automatically. It is more common to simply open the database in New().


New proc (database)

See also:
database datum
Open proc (database)
Format:
New(filename)
Args:
filename: The database filename to open (optional)

Creates a new database datum, and opens the file if a filename is provided.


database query datum

See also:
database datum
procs (database query)
stddef.dm file

This datum lets you create a query for a database, which can be run with the Execute() proc. The datum can be reused after a query is run by calling Clear() and adding new text with Add().


procs (database query)

See also:
database datum
database query datum
procs (database)

Built-in database query procs:

database/query/proc
Add
Clear
Close
Columns
Error
ErrorMsg
Execute
GetColumn
GetRowData
New
NextRow
Reset
RowsAffected

Add proc (database query)

See also:
database query datum
Clear proc (database query)
Format:
Add(text, item1, item2, ...)
Args:
text: Text to add to the query
item1, item2, etc.: Items that will replace question marks in text

Adds text to a database query. If this datum was already used to run a query, Clear() will be called automatically.

If your text includes question marks, they will be replaced with the other items listed in the proc arguments. If that item is a string, quotes will be put around it for the query text. Files in the cache (such as icons) will be added as BLOB values.

After the query has been built, call Execute() to run it.

Example:

var/database/db = new("mydb.db") var/database/query/q = new q.Add("INSERT INTO quests (name, quest, complete) VALUES (?,?,?)", usr.key, quest_name, 1) q.Execute(db)

In the example above, the query text might look like this:

INSERT INTO quests (name, quest, complete) VALUES ('Tom','Save the Dog',1)


Clear proc (database query)

See also:
database query datum
Add proc (database query)
Format:
Clear()

Clears the query text so you can begin creating a new query. This is called automatically if you already called Execute() for the last query used by this datum.


Close proc (database query)

See also:
database query datum
Clear proc (database query)
Reset proc (database query)
Format:
Close()

Ends a query that is in progress. This is usually done automatically and shouldn't be necessary to call in most cases.


Columns proc (database query)

See also:
database query datum
Execute proc (database query)
GetColumn proc (database query)
GetRowData proc (database query)
NextRow proc (database query)
Format:
Columns()
or
Columns(column)
Args:
column: The Nth column whose name should be read

Returns a list of column names for the current query, or the name of the Nth column.

You must call Execute() before calling Columns().


Error proc (database query)

See also:
database datum
database query datum
ErrorMsg proc (database query)
Format:
Error()

Returns the error code last received for this query.


ErrorMsg proc (database query)

See also:
database datum
database query datum
Error proc (database query)
Format:
ErrorMsg()

Returns the error message last received for this query.


Execute proc (database query)

See also:
database datum
database query datum
Add proc (database query)
Close proc (database query)
GetColumn proc (database query)
GetRowData proc (database query)
NextRow proc (database query)
Reset proc (database query)
RowsAffected proc (database query)
Format:
Execute(database)
Args:
database: A /database datum with the database to be queried, or the name of the database file

Runs a database query. Once the query is run, if the query is supposed to returns any rows you can call NextRow() until finished, and then GetColumn() or GetRowData() to get the information from each row. For queries that cause changes, RowsAffected() is also a useful call.

The database argument is optional after the first time you use it.

You can use a filename instead of a /database datum, as a shortcut; the datum will be created for you.

After a query is executed, calling Add() to create new query text will clear out the old query text automatically.

Example:

var/database/db = new("mydb.db") var/database/query/q = new("SELECT quest,complete FROM quests WHERE name=?", usr.key) if(!q.Execute(db)) return null var/list/completed_quests = new while(q.NextRow()) var/row = q.GetRowData() if(row["complete"]) completed_quests[row["quest"]] = 1 return completed_quests

GetColumn proc (database query)

See also:
database datum
database query datum
Columns proc (database query)
Execute proc (database query)
GetRowData proc (database query)
NextRow proc (database query)
Reset proc (database query)
Format:
GetColumn(column)
Args:
column: The column number whose value should be retrieved

Gets the value from the Nth column in this row of results. If you haven't already called Execute() and NextRow(), you should do that first.

To get the name of the column, not the value for this row, call Columns(column) instead.

The value returned depends on what type the database table thinks it is. For instance if you defined a column as INTEGER or FLOAT, the value should be a number. TEXT is still text, and null values are returned as null. If an icon was saved into a BLOB field, the result is an icon file.


GetRowData proc (database query)

See also:
database datum
database query datum
Columns proc (database query)
Execute proc (database query)
GetColumn proc (database query)
NextRow proc (database query)
Reset proc (database query)
Format:
GetRowData()

Returns a list with the current result row for this query. If you haven't already called Execute() and NextRow(), you should do that first.

The list returned is an associative list with name=value pairs. A typical result might look like this:

list("name" = "Tom", "quest" = "Save a Dog", complete = 1)

The values returned depend on what type the database table thinks they are. For instance if you defined a column as INTEGER or FLOAT, the value should be a number. TEXT is still text, and null values are returned as null. If an icon was saved into a BLOB field, the result is an icon file.


New proc (database query)

See also:
database datum
database query datum
Add proc (database query)
Format:
New(text, item1, item2, ...)
Args:
text: Text to add to the query
item1, item2, etc.: Items that will replace question marks in text

Creates a new query and adds text by automatically calling Add(). See the Add proc for more information.

Call Execute() to run the query.


NextRow proc (database query)

See also:
database datum
database query datum
Execute proc (database query)
GetColumn proc (database query)
GetRowData proc (database query)
Reset proc (database query)
Format:
NextRow()

If there are result rows in this query (Execute() must be called to run the query first), NextRow() will retrieve the next row and return 1 if it found a row, or 0 if the results are all finished. NextRow() is typically called in a while() loop.

After calling NextRow(), you can call GetColumn() or GetRowData() to get information about the results in this row.

Call Reset() if you want to rewind the query to the beginning.


Reset proc (database query)

See also:
database datum
database query datum
Execute proc (database query)
NextRow proc (database query)
Format:
Reset()

If a query returns any rows of results, Reset() will go back to the beginning just after Execute() was called. This is useful if you have called NextRow() repeatedly to retrieve a number of rows, but need to go back to the start of the query for some other reason. This can also be used to count the total number of result rows if needed, but for best performance that isn't recommended.


RowsAffected proc (database query)

See also:
database datum
database query datum
Execute proc (database query)
RowsAffected proc (database query)
Format:
RowsAffected()

After running Execute() on a query that changes rows in the database (for instance, an UPDATE query), this proc returns the number of rows that were changed. This can be useful if you need to know whether a query actually did anything.


datum

See also:
atom
procs (datum)
vars (datum)

The datum object is the ancestor of all other data types in DM. (The only exceptions are currently /world, /client, /list, and /savefile, but those will be brought into conformance soon.) That means that the variables and procedures of /datum are inherited by all other types of objects.

When you define a new "top level" object, if you do not specify a parent_type, it defaults to /datum.

Example:

datum //definitions to be shared by all object types proc/DebugMe() world.log << "/datum properties:" world.log << "type: [type]" world.log << "parent_type: [parent_type]" return ..() MyType var myvar = "test" DebugMe() world.log << "/MyType properties:" world.log << "myvar: [myvar]" return ..() //this calls /datum/proc/DebugMe()

procs (datum)

Built-in datum procs:

datum/proc
New
Del
Write
Read
Topic

Del proc (datum)

See also:
del proc
garbage collection
Format:
Del()
When:
Called when the object is destroyed, for example by using the del instruction.
Default action:
Delete the object. The contents of atomic objects are also destroyed at this time, as though del were called on each one of them.

When the world is destroyed, the Del() proc is not automatically called. The only object for which it is called is /world. If you need the Del() proc for a particular object to be called at that time, you should explicitly call it from world/Del().

Note: Always call ..() at the end of the proc if you override it.


New proc (datum)

See also:
New proc (atom)
New proc (client)
new proc
Format:
New()
When:
Called when the datum is created, for example by using new, when reading an object that was stored in a savefile, or when the world is initially created.
Default action:
None.

You can use the New() procedure to do more complicated initializations than are possible in the object definition where you assign the initial value of variables to constants.

The following example makes use of the "Location" parameter that is passed to objects of type /atom. You can pass any number of additional arguments to New() by passing them to the new instruction which creates the object.

Example:

mob/night var/mob/squire/my_squire New(Location) my_squire = new(Location) return ..()

Also note that the type of object being created in this case was automatically inferred from the variable type on the left-hand side of the assignment. That's a handy little DM short-cut.


Read proc (datum)

See also:
>> operator (savefile)
Write proc (datum)
tmp vars
Format:
Read(savefile/F)
When:
Called when the object is read from a save file.
Args:
F: the save file being read
Default action:
Read the value of each variable from a directory by the same name as the variable. Variables marked tmp, global, or const and variables for which there is no directory are skipped.

Topic proc (datum)

See also:
Topic proc (client)
ref text macro
Format:
Topic(href,href_list[])
Args:
href: the hyperlink data (following ? in the URL).
href_list: key/value list (from params2list(href)).

This procedure is called by the default client.Topic() proc when the href contains a parameter called "src" containing an object reference.

Example:

mob/verb/test() usr << "Click <a href='?src=\ref[src];action=startgame'>here</a>!" mob/Topic(href,href_list[]) switch(href_list["action"]) if("startgame") usr << "Starting game..."

The above example uses an embedded reference to the player's own mob to create a hyperlink to that mob's Topic() proc. You can easily add different actions, parameters, and so forth. Just remember that the parameter values are always stored as text, so you need to convert those to whatever data format you need using procedures such as text2num(), locate(), etc.

Always validate the input in Topic() calls to make sure it's correct and the query you're recieving is legitimate.


Write proc (datum)

See also:
<< operator (savefile)
Read proc (datum)
initial proc
issaved proc
tmp vars
Format:
Write(savefile/F)
When:
Called when the object is written to a save file.
Args:
F: the save file being written to
Default action:
Write the value of each variable to a directory by the same name as the variable. Variables marked tmp, global, or const and variables which are equal to their initial value are skipped.

vars (datum)

Built-in datum vars:

datum/var
type
parent_type
tag
vars

parent_type var

Default value:
The path of the object definition that contains this one.

This variable is set at compile-time to specify the inheritance of an object type. Normally, a new type of object inherits its variables and procedures from the object type that contains it. For example:

obj var weight color sword //parent type of 'sword' defaults to /obj weight = 30 color = "black"

Explicitly setting the parent type allows you to put the object definition any place you want. That often means putting it at the top "root" level. Example:

Armor parent_type = /obj var strength plate //parent type is /Armor, which in turn inherits from /obj weight = 100 color = "rusty" strength = 10

If you don't specify the parent_type for an object defined at the top level, it defaults to /datum, which (with just a couple exceptions) is the ultimate ancestor of all object types. You could use that fact to define procedures or variables that you need all of your objects to share.

Example:

datum proc/Copy(datum/O) MyType var foo Copy(MyType/O) foo = O.foo return ..()

tag var (datum)

See also:
locate proc
Default value:
null

This may be assigned to a unique text string identifying a particular object. A reference to the object can then be obtained by using locate().

One reason to use tags is when making references in the code to objects and locations that will be created on the map. You can simply edit the object in the map editor, set its tag, and then use that in the code relating to the object.

The following example demonstrates how to set a tag and use it to obtain a reference to an object.

Example:

mob/verb/test() var/obj/O = new() O.tag = "My Object" var/obj/O2 = locate("My Object") ASSERT(O == O2) //this should always be true

Setting a tag to "" or null removes it. Any object with a non-empty tag is immune to garbage collection, since the tag is treated as an implicit reference to that object.


type var (datum)

Default value:
The "type path" of the object definition.

This variable is read-only.

mob/verb/test() usr << type //displays "/mob"

vars list var (datum)

See also:
initial proc
issaved proc
list
list associations
vars list var (global)

This is a list of all the variables belonging to an object. The items in the list are the variable names. If the variable name is used as an index into the list, the value of that variable is accessed.

Example:

mob/verb/dump() var/V for(V in vars) usr << "[V] = [vars[V]]"

This example displays all the variables belonging to your mob.


exception

See also:
try and catch statements
Error proc (world)
throw statement
EXCEPTION proc
stddef.dm file
Vars:
name: A text string (such as an error message) or other value
file: The filename where the error occurred, if debugging info is present
line: The line where the error occurred, if debugging info is present
desc: Detailed error info including call stack, only used when sent to world.Error()

This datum is created automatically when a runtime error is encountered, if it happens within a try/catch block or you have defined a global error handler with world.Error(). (The New() proc is not called when this happens.) This provides a convenient package for getting file and line number info associated with an error.

If you throw your own exceptions, you do not have to use this, but the EXCEPTION macro is provided to easily create one with the current file and line number.

The desc value is only filled in when you have a world.Error() handler and there is no try/catch handling this error. Just like when no handler is present, less detail will be provided after multiple runtime errors have occurred. This only exists as a convenience feature for logging errors if you want to use something other than world.log.


icon object

See also:
procs (icon)
icons
image objects
stddef.dm file

An /icon object is created by loading an icon file into memory for direct access and manipulation. In order to be displayed, an /icon object always gets converted back into an icon file; this happens automatically when you assign atom.icon to an /icon object, since that variable may only refer to a static icon file, rather than a dynamic memory object.

To create an /icon object, simply use new/icon(), or the short-cut icon() proc. The following example loads an icon file, reddens it, and then assigns it back to the player's icon, which implicitly creates a new icon file.

Example:

mob/verb/test() var/icon/I = new('player.dmi') I.Blend(rgb(40,0,0)) usr.icon = I

Note that merely displaying different icon states or directions can generally be achieved without any icon manipulation, which saves quite a bit of overhead. For example, the variables atom.icon_state and atom.dir can be used to control how atom.icon is displayed, without any need for generating a new icon file.

Many things that used to require icon manipulation may not need you to do so anymore, as DM has evolved new capabilities.

Operation/icon procNew method
Multiplying by colorBlend or SetIntensity procscolor var
Adding colorBlend proccolor var (using color matrix)
Applying color matrixMapColors proc
RotationTurn proctransform var
Flipping horizontal/verticalFlip proc
ScalingScale proc
Overlaying/underlaying another iconBlend proc + ICON_OVERLAYOverlay/underlay + KEEP_TOGETHER
Layering filter

Note: Anything you can do with an atom var instead of using icon manipulation procs will usually perform much better. Games that use the new methods use fewer resources, use less memory, and also usually look better too.


procs (icon)

See also:
icon
icon/proc
New
IconStates
Turn
Flip
Shift
SetIntensity
Blend
SwapColor
DrawBox
Insert
MapColors
Scale
Crop
GetPixel
Width
Height

Blend proc (icon)

See also:
icon
procs (icon)
overlays var (atom)
rgb proc
Format:
Blend(icon,function=ICON_ADD,x=1,y=1)
Args:
icon: an icon file, /icon object, or color
function: the blending operation to use
x, y: the position to blend the icon

The valid blending operations are:

The result is a combination of each corresponding pixel in the two icons. In all but ICON_OVERLAY, ICON_UNDERLAY, and ICON_OR, the transparent regions of the two icons are ORed together. That means if either icon is transparent on a given pixel, the result will be transparent. With ICON_OVERLAY or ICON_UNDERLAY, on the other hand, the original icon shows through wherever the top icon is transparent, giving the same effect as an overlay object, but resulting in only a single icon. In ICON_OR, the transparent regions are ANDed together; solid pixels are added together where they exist in both icons, or just pass through if the other icon is transparent at that pixel.

In addition to blending with an icon, an rgb() value may also be specified. This is treated identically to an icon of that same solid color, except that the x and y arguments will be ignored. Blending with a color blends the whole icon.

By default, the icons will line up at their lower left corners. If you want to position the second icon in a different place for blending, use the x and y arguments to specify where its lower left corner will be. 1,1 is the default, which is the lower left. 11,1 for instance would be 10 pixels to the right, and 1,21 would be 20 pixels up.


Crop proc (icon)

See also:
icon
procs (icon)
icon_size var (world)
map_format var (world)
Big icons
Tiled icons
Format:
Crop(x1,y1,x2,y2)
Args:
x1,y1: Coordinates of one corner of the rectangle (1,1 is the lower left)
x2,y2: Coordinates of the other corner

A portion of the current icon is cropped (cut). If the crop region extends outside the icon, it will be padded with transparent pixels.

If using the TILED_ICON_MAP value for map_format, all icons must be even multiples of world.tile_size, so the icon will be padded with transparent pixels to the top and right as needed.

Example:

// start with a simple icon var/icon/I = new('circle.dmi') // take the upper right 16x16 chunk I.Crop(17,17,32,32) // that chunk now appears in the lower left corner icon = I

DrawBox proc (icon)

See also:
icon
procs (icon)
rgb proc
Format:
DrawBox(rgb,x1,y1,x2=x1,y2=y1)
Args:
rgb: rgb(red,green,blue) or null
x1,y1: Coordinates of one corner of the rectangle (1,1 is the lower left)
x2,y2: (optional) Coordinates of the other corner

A rectangle (filled) of the given color is drawn over every frame in the icon. If x2 and/or y2 are omitted, a line or a single pixel is drawn. To draw a transparent box instead of an opaque color, use null as the color.


Flip proc (icon)

See also:
Turn proc (icon)
dir var (atom)
icon
procs (icon)
Format:
Flip(dir)
Args:
dir: direction in which to flip over the icon

This flips the icon over in the specified direction. For example, Flip(NORTH) would be like turning the icon upside down by grabbing the bottom edge and flipping it up over the top edge. You would get the same result by doing Flip(SOUTH). In general, this is not the same as turning the icon by 180 degrees, because it produces a mirror image.

If an icon is square, it may be flipped diagonally.


GetPixel proc (icon)

See also:
icon
procs (icon)
rgb proc
Format:
GetPixel(x, y, icon_state, dir=0, frame=0, moving=-1)
Args:
x,y: coordinates of the pixel to grab; 1,1 is the lower left corner
icon_state: a specific icon_state to use (may be null)
dir: a specific direction of this icon to use
frame: a specific animation frame to use (1 is the 1st frame)
moving: non-zero for only movement states, 0 for non-movement states, or null (default) for either

This finds the icon_state and the right animation/direction frame of your choosing (it will pick the first one available if you don't specify) and returns the rgb() value of a pixel at that location, in "#RRGGBB" form. If the pixel is totally transparent, it returns null. If the pixel is partially transparent, an alpha component is also returned in "#RRGGBBAA" form.


Width proc (icon)

See also:
icon
procs (icon)
Height proc
Format:
Width()

This finds the width, in pixels, of the icon.


IconStates proc (icon)

See also:
icon
procs (icon)
icon_states proc
Format:
IconStates(mode=0)
Args:
mode: see icon_states proc

This returns a list of all icon state text strings that exist in the /icon object. This works in exactly the same way as icon_states(icon).


Insert proc (icon)

See also:
procs (icon)
New proc
map_format var (world)
Big icons
Tiled icons
Format:
Insert(new_icon,icon_state,dir,frame,moving,delay)
(supports named arguments)
Args:
new_icon: an icon file or /icon object to insert
icon_state: an optional text string, specifying a single icon state to change or add to this icon
dir: an optional direction; the inserted icon will only be added for this direction
frame: an optional animation frame (starting at 1); the inserted icon will only be added for this frame
moving: Non-zero to insert as a movement state, 0 for a regular non-movement state
delay: 0 or null to leave unchanged; positive to set delay for a frame and turn rewind off; negative to set delay and rewind

This adds additional states or images to an existing icon, allowing you to build directional, animated, and multi-state icons on the fly. If the state you wish to insert already exists in the file, it will be altered; otherwise it will be added. An animation may be built a piece at a time, for example by inserting an icon into the NORTH direction for animation frame 3.

Example:

// start with a non-animated arrow icon var/icon/I = new('arrow.dmi') // make a new state called "blink" var/icon/J = new('arrow.dmi') I.Insert(J, "blink", delay=-1) // set rewind flag // create darker shades of the arrow var/n = 2 for(var/light=9, light>=5, light--) J = new('arrow.dmi') J.SetIntensity(light/10) I.Insert(J, "blink", frame=n++) // congratulations, you have a pulsating arrow icon = I

The icon resulting from this example has two states: The original arrow, and a new state called "blink" that pulsates between full and ½ luminance. To use the blinking state after that, set the atom's icon_state to "blink".

(Note for animations: When building an animated icon_state from scratch, you can only add 16 new animation frames at a time; i.e., frame<=total_frames+16. Higher values for frame will be ignored. This is a safety precaution.)

If you insert an icon of a different size, the src icon will be resized to match the size of new_icon. (The only exception is if you are using the TILED_ICON_MAP map_format, and new_icon is a single tile being inserted as a chunk into a larger icon. If icon_state, such as "2,0" or "open 0,0", already exists in src as one of its smaller pieces, then new_icon will be inserted in its place.)

When inserting an individual animation frame, you can change the delay for just that frame only. If you don't specify a delay, the nearest frame's delay will be used. If this is the first frame being inserted into an icon, then the delay will default to 1 tick. Remember, if your delay is positive, it will turn off the rewind flag for that entire icon state; negative will turn it on.


MapColors proc (icon)

See also:
icon
procs (icon)
rgb proc
Format:
MapColors(rr, rg, rb, gr, gg, gb, br, bg, bb, r0=0, g0=0, b0=0)
or
MapColors(r_rgb, g_rgb, b_rgb, rgb0=rgb(0,0,0))
or
MapColors(rr, rg, rb, ra, gr, gg, gb, ga, br, bg, bb, ba, ar, ag, ab, aa, r0=0, g0=0, b0=0, a0=0)
or
MapColors(r_rgba, g_rgba, b_rgba, a_rgba, rgba0)
Args:
rr: portion of old red component -> new red component
rg: portion of old red component -> new green component
rb: portion of old red component -> new blue component
ra: portion of old red component -> new alpha component
r0: new base red component
...
or
r_rgb: red component is converted to this color
g_rgb: green component is converted to this color
b_rgb: blue component is converted to this color
rgb0: this color is added to the result

This is used for complex color mapping that can be used for many special effects. For the number form, values usually range from 0 to 1, but you can use anything you like, including negative numbers. 1 means 100% of the original color will be used. If rg=1, for example, then the amount of red in the original icon becomes the same amount of green in the new icon's colors.

There is also an alternate form that can use rgb() values instead, though it is less flexible. r_rgb is the color that will be used in place of 100% red; any darker shades of red will become a darker shade of that color. g_rgb converts green to another color, and b_rgb converts blue to still another color, and all of them are added together.

Either of these calls change the icon to grayscale:

icon.MapColors(0.3,0.3,0.3, 0.59,0.59,0.59, 0.11,0.11,0.11, 0,0,0) // or... icon.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))

The calculations are as follows:

Or this will make a nice moonlight effect:

icon.MapColors(0.2,0.05,0.05, 0.1,0.3,0.2, 0.1,0.1,0.4, 0,0,0) // or... icon.MapColors(rgb(51,13,13), rgb(26,77,51), rgb(26,26,102), rgb(0,0,0))

Or a negative icon (invert all colors):

MapColors(-1,0,0, 0,-1,0, 0,0,-1, 1,1,1)

The longer formats of MapColors() will allow you to also change alpha colors.


New proc (icon)

See also:
icon
procs (icon)
image proc
new proc
Format:
New(icon,icon_state,dir,frame,moving)
(supports named arguments)
Args:
icon: an icon file or /icon object
icon_state: an optional text string, specifying a single icon state to load
dir: an optional direction to extract
frame: an optional animation frame to extract
moving: Non-zero to extract only movement states, 0 for non-movement states, or null (default) for both

You generally don't call this directly but via new(). The specified icon file is loaded into memory for direct access and manipulation.

If the icon state is not specified, all icon states are loaded. Ditto for the direction, animation frame, or preference for movement states. Animation frames are numbered from 1 and up, so frame=4 is the 4th frame.

(Movement states are special versions of an existing icon_state with the same name, but appear in the Dream Maker editor with an "M" indicator. These states are used for animation when the atom using the icon_state moves from one tile to the next; otherwise only the normal non-moving state is displayed.)

The following contrived example, loads the EAST facing default icon state "" from the user's icon file, rotates that a bit, and then creates a new icon file for the user.

Example:

mob/verb/test() var/icon/I = new(usr.icon,icon_state = "",dir = EAST) I.Turn(90) //rotate clockwise 90 degrees usr.icon = I

Note that merely displaying different icon states or directions can generally be achieved without any icon manipulation, which is good, because it saves quite a bit of overhead. For example, the variables atom.icon_state and atom.dir can be used to control how atom.icon is displayed, without any need for generating a new icon file.


Scale proc (icon)

See also:
icon
procs (icon)
icon_size var (world)
map_format var (world)
Big icons
Tiled icons
Format:
Scale(width, height)
Args:
width,height: size of the new icon

The current icon is scaled to a new size.

If world.map_format is set to TILED_ICON_MAP and the new size is not in multiples of world.icon_size, the icon will be padded with transparent pixels to the top and right as needed. See map_format for more information.

Scale() automatically performs antialiasing to avoid unwanted artifacts.


SetIntensity proc (icon)

See also:
icon
procs (icon)
MapColors() proc (icon)
Format:
SetIntensity(r,g=r,b=r)
Args:
r: red component
g: green component
b: blue component

This multiplies the pixel intensities by the specified amounts. A value greater than 1.0 increases the intensity and a value less than 1.0 decreases the intensity.


Shift proc (icon)

See also:
dir var (atom)
icon
procs (icon)
Format:
Shift(dir,offset,wrap=0)
Args:
dir: direction in which to shift the icon
offset: distance to shift the pixels
wrap: if true, causes shifted pixels to wrap around to the other side

This moves all of the pixels by the specified amount in a direction. For example, Shift(NORTH,1) would move everything one pixel to the north.

By default, pixels that move off the edge are not wrapped around; transparent pixels are shifted onto the other side. Calling with wrap=1 causes it to shift the pixels around to the other side.


SwapColor proc (icon)

See also:
icon
procs (icon)
rgb proc
Format:
SwapColor(old_rgb,new_rgb)
or
SwapColor(old_rgba,new_rgba)
Args:
old_rgba: the old rgba value to be replaced
new_rgba: the new rgba value to use in its place

This causes a color value in the icon's palette to be changed. You can use null in place of an RGB or RGBA value.

If the old color is a full RGBA color with an alpha value, such as rgb(1,2,3,4) or "#01020304", then that exact color is the only one changed.

If the old color is an RGB value with no alpha specified, such as rgb(1,2,3) or "#010203", then that color will change to the new one regardless of its alpha value, and the original icon's alpha will be kept intact. (If the new color is totally transparent, however, then the old color will be replaced with full transparency.)


Turn proc (icon)

See also:
Flip proc (icon)
dir var (atom)
icon
procs (icon)
Format:
Turn(angle)
Args:
angle: an angle in degrees

This rotates the icon clockwise by the specified amount.

Example:

mob/verb/drink() //this effect is very confusing! var/icon/I = new(usr.icon) I.Turn(90) usr.icon = I usr << "You feel a little tipsy!" sleep(200) I.Turn(-90) //turn it back usr.icon = I //should have just saved original value

If an icon is not square, it cannot be turned.


Height proc (icon)

See also:
icon
procs (icon)
Width proc
Format:
Height()

This finds the height, in pixels, of the icon.


image objects

See also:
icon var (atom)
image proc
vars (image)
images var (client)
overlays var (atom)
override var (atom)

The /image type contains data used to create a virtual image. Unlike other atomic objects, this object is a purely visual effect. It always appears attached to some other object and it behaves in every way as though it were part of that object (e.g. if the user clicks on it, this counts as a click on the atomic object, not the image).

One reason for creating images is player-by-player control over visibility. Images only become visible when they are explicitly output to players:

Example:

var/image/I = image('icon.dmi',usr) //make an image attached to usr usr << I //allow usr to see it

Images are also useful in the creation of overlays. Overlays are like images, since they are always attached to another object, but overlays obey the normal rules of visibility, so they are more convenient when you do not want to hide the effect from anybody. An overlay can be created directly from an icon file (or icon state), but when one wishes to override some additional parameter, the image() instruction is a convenient way to do it.

Example:

usr.overlays += image('shirt.dmi',icon_state = "red")

In the above example, the icon state of an overlay was set by creating the overlay from an image with the desired icon state. Note that after the creation of an overlay, no link remains between the overlay and the object that was used to create it. If you change the image after that time, it will not change the overlay, which is simply a "snapshot" of the original image.


vars (image)

/image/var
alpha
appearance
appearance_flags
blend_mode
color
icon
icon_state
text
dir
filters
loc
maptext
maptext_width
maptext_height
maptext_x
maptext_y
overlays
override
pixel_x
pixel_y
pixel_w
pixel_z
plane
render_source
render_target
transform
underlays
vis_contents
x
y
z
type
tag
parent_type

loc var (image)

The location of an image specifies the object to which the image is attached. Unless the image drawing layer is specified, the default will make it appear above this object, as though it were an overlay.

Note that the image is not inside the specified location. In other words, this loc variable does not behave like /atom/movable/var/loc which specifies the container object. It is more like the image is on top of the specified object. If the object moves, the image will automatically move around with it.


list

See also:
list associations
list proc
islist proc
procs (list)
vars (list)

Lists are used to represent groups of objects. Like objects, they have vars and procs associated with them. In order to access these attributes, list vars must be declared of type /list. These may then be assigned to existing lists, or used to create new lists.

Example:

var/list/L // list reference L = world.contents // assign to existing list L = new/list() // make a new list L = new() // make a new list (implicit type) L.Add("futz") // L contains: "futz" del(L) // delete L

Lists created with 'new()' have a default length of 0; this can be overridden by specifying the size; that is, new/list(size) creates a list with size (null) elements.

The 'list()' proc may be used to more easily initialize list data.

Example:

var/list/L L = list("futz",3) // L contains: ("futz", 3)

Alternatively, lists may be declared by using brackets, '[]'. Empty brackets indicate a list reference, exactly as /list does, so list/L is equivalent to L[]. Setting an initial size within the brackets, for instance, L[10], creates a list of that initial size.

Example:

var/L[] // same as var/list/L: list reference var/M[10] // initially empty list of size 10 L = M // L is now an empty list of size 10

Once a list L is declared, a specific item can be accessed by putting its index in the brackets: L[index].

Indices range from 1 to len. If the length of the list is changed, existing elements in the list will be preserved if they are less than the new length. New elements in the list will be given the initial value of null.

Example:

var/L[5] // initial length of 5 var/i for(i=1, i<=L.len, i++) L[i] = i // L contains: (1,2,3,4,5) L.len = 7 // expand list // L contains: (1,2,3,4,5,null,null) del(L) // destroy list

Multi-dimensional lists may be created by making a list of lists.

Example:

var/grid[10][5] grid[1][1] = 1 grid[1][2] = 2 ...

Such a list may also be created by using new(). As in the previous example, the next one creates a list of 10 lists each having 5 elements.

Example:

var/grid = new/list(10,5)

list associations

See also:
list
list proc
list2params proc
params var (world)
params2list proc
vars list var (datum)

Each unique text string or object in a list may be associated with another value. This is done by using the item as an index into the list.

Example:

var/params[0] params["player"] = "James Byond" params["score"] = 2000 //List now contains ("player","score") //These are associated with ("James Byond",2000) usr << "Looping through list items:" var/p for(p in params) usr << "[p] = [params[p]]" usr << "Looping through array indices:" var/i for(i=1,i<=params.len,i++) p = params[i] usr << "[p] = [params[p]]"

The above example illustrates the typical way in which list associations are managed. Note that an item in the list may be added by assigning its associated value. The example could have started by doing params.Add("player","score"), but that would have been redundant.

Both for loops in the example have the same effect. The first one loops through each item in the list, and displays it along with its associated value. The second loop achieves the same thing by looping through the numerical indices (referred to as array indices as opposed to associative indices).

Since numerical indices are treated differently, you may not assign an associated value to a numerical list item. Associations must have a text string or object reference as the index item.

Associated values default to null if none is assigned. This is also the value returned when the supplied index item does not exist in the list. The list defined above, for example, would return null for params["time"].

The list() instruction may also be used to create associative lists.

Example:

var/list/lst = list("player" = "James Byond", "score" = 2000)

When the index values happen to be text strings that satisfy all the requirements for variable names, this may also be written in a convenient short-hand:

var/list/lst = list(player = "James Byond", score = 2000)

In other words, this is exactly the same syntax as for named arguments.


list operators

These operators are used for accessing list items.

[] operator
?[] operator

These operators all have special meaning when applied to lists.

+ operator
+= operator
- operator
-= operator
| operator
|= operator
& operator
&= operator
^ operator
^= operator
in operator

procs (list)

See also:
list
list operators

Built-in list procs:

list/proc
Add
Copy
Cut
Find
Insert
Join
Remove
RemoveAll
Splice
Swap

Add proc (list)

See also:
+ operator
Remove proc (list)
RemoveAll proc (list)
Format:
list.Add(Item1,Item2,...)
Args:
One or more items to add to the list.

Appends the specified items to the list. If an argument is itself a list, each item in the list will be added.


Copy proc (list)

See also:
Cut proc (list)
Format:
list.Copy(Start=1,End=0)
Returns:
A new list.
Args:
Start: The list position in which to begin the copy.
End: The list position immediately following the last element to be copied.

Copy list[Start] through list[End-1] into a new list. The default end position of 0 stands for the position immediately after the end of the list, so by default the entire list is copied.


Cut proc (list)

See also:
Copy proc (list)
Insert proc (list)
Format:
list.Cut(Start=1,End=0)
Args:
Start: The list position in which to begin the cut.
End: The list position immediately following the last element to be removed.

Remove the elements between list[Start] and list[End-1], decreasing the size of the list appropriately. The default end position of 0 stands for the position immediately after the end of the list, so by default the entire list is deleted.


Find proc (list)

Format:
list.Find(Elem,Start=1,End=0)
Returns:
The first position of elem in list, or 0 if not found.
Args:
Elem: The element to find.
Start: The list position in which to begin the search.
End: The list position immediately following the end of the search.

Find the first position of Elem in the list. Elements between Start and End are searched. The default end position of 0 stands for the position immediately after the end of the list, so by default the entire list is searched.


Insert proc (list)

See also:
Cut proc (list)
Copy proc (list)
Swap proc (list)
Format:
list.Insert(Index,Item1,Item2...)
Returns:
The index following the inserted items.
Args:
Index: The index where the new item will be inserted. Any value already at that index will be pushed forward.
Item1: A value or list of values to insert.
Item2...: (optional) Additional items to insert, immediately after the previous item(s).

Insert values into a list at a specific point. Using Index=0 or Index=list.len+1 is the same as adding to the list.

If any of the items you insert is itself a list, its elements will be inserted instead of the list itself.

Note: This proc doesn't work with many special lists such as contents or overlays.


Join proc (list)

See also:
jointext proc
Format:
list.Join(Glue,Start=1,End=0)
Returns:
A text string made up of the items in this list, joined together by Glue.
Args:
Glue: The text that will go between each item.
Start: The list item on which to begin.
End: The list item immediately following the last item to be joined.

This is exactly the same as calling jointext(List,Glue,Start,End), and is provided for convenience.


Remove proc (list)

See also:
- operator
Add proc (list)
RemoveAll proc (list)
Format:
list.Remove(Item1,Item2,...)
Returns:
1 if any items removed, 0 if not.
Args:
One or more items to remove from the list.

Removes the specified items from the list. If an argument is itself a list, each item contained in it will be removed. Removal starts at the end of the list (highest index) so that this operation is an exact reversal of Add().


RemoveAll proc (list)

See also:
Add proc (list)
Remove proc (list)
Format:
list.RemoveAll(Item1,Item2,...)
Returns:
Number of items removed.
Args:
One or more items to remove entirely from the list.

Removes all copies of the specified items from the list. If an argument is itself a list, each item contained in it will be removed.

This is basically a faster version of the statement while(list.Remove(Item1,Item2,...)) with an empty code block. For large lists this might be a big improvement because the list doesn't have to be traversed every time.


Splice proc (list)

See also:
Copy proc (list)
Cut proc (list)
Insert proc (list)
splicetext proc
Format:
list.Splice(Start=1,End=0,Item1,Item2...)
Args:
Start: The list index where the splice will begin.
End: The index immediately following the last item to be cut from the list. 0 is the end of the list.
Item1, Item2...: Items to be inserted.

Cuts out items from a list, and inserts new items in their place. This is basically equivalent to calling list.Cut(Start,End) and then calling list.Insert(Start,Item1,Item2...), but faster.

Example:

var/list/L = list("apple","banana","orange","pear") // cuts "banana" and "orange" and inserts four new items L.Splice(2,4,"firetruck","camel","joystick","balloon") // prints apple, firetruck, camel, joystick, balloon, pear for(var/item in L) usr << item

As with Insert(), any items that are lists will insert their contents instead of themselves.

The Start and End index values can be negative, which count backwards from the end of the list. If the index values are out of range, there will be no error; they will simply be clamped to the beginning or end of the list. If End comes before Start, the two values are swapped.

Note: This proc doesn't work with many special lists such as contents or overlays.


Swap proc (list)

See also:
Cut proc (list)
Copy proc (list)
Insert proc (list)
Format:
list.Swap(Index1,Index2)
Returns:
Nothing.
Args:
Index1: The index (1 to list.len) of one of the items to swap.
Index2: The index of the other item.

Swap two items in a list. If the list has associated values, they will be preserved. This is most useful for user-defined sorting routines.

Example:

var/item var/list/L = list("orange" = 3, "green" = 2, "blue" = 5) for(item in L) world << "[item] -> [L[item]]" world << "" L.Swap(1, 3) for(item in L) world << "[item] -> [L[item]]"

Result:

orange -> 3 green -> 2 blue -> 5 blue -> 5 green -> 2 orange -> 3

Note: This proc doesn't work with many special lists such as contents or overlays.


vars (list)

Built-in list vars:

list/var
len

len var (list)

See also:
+ operator
+= operator
- operator
-= operator

This is the length of the list. Increasing it expands the list, initializing all new elements with null. Decreasing it contracts the list, making old elements inaccessible.


map

See also:
#include directive
area var (world)
maxx var (world)
turf var (world)
Format:
#include "mapname.dmm"

One or more map files may be loaded into the world's map. These are loaded into successive z-levels. If no map files are specified, the default project map file will be used. This file has the same name as the project but has the extension .dmm.

If no map files are loaded, the world's map size is determined by the world variables maxx, maxy, and maxz. The default content of this map is determined by the world variables turf and area.

Example:

#include "level1.dmm" #include "level2.dmm" #include "level3.dmm"

matrix

See also:
matrix proc
matrix operators
matrix procs
transform var (atom)
stddef.dm file

To display rotation, scaling, and other transformations on atoms, DM uses 2D matrices. The /matrix datum is a convenient way of handling the numbers involved, as it can be easily manipulated. There are six vars, a through f, laid out like so:

          a d 0
x y 1  *  b e 0  =  x' y' 1
          c f 1

When an x,y point is multiplied by the matrix, it becomes the new point x',y'. This is equivalent to:

x' = a*x + b*y + c
y' = d*x + e*y + f

The default matrix is:

1 0 0
0 1 0
0 0 1

Matrices are created with the matrix() proc, or by calling new/matrix(). (See the matrix() proc for examples.) They are also created as needed whenever you read from atom.transform or use certain operators.

Manipulation of matrices can be done with operators, or with procs. You can do the following with them:

When you've built your matrix, you can assign it to atom.transform to change the way that atom is displayed.

The matrices supported by this datum are not the same kind used to transform colors, as in the atom.color var and icon.MapColors() proc. For color matrices, see color matrix.


matrix operators

See also:
matrix
matrix procs
See also:
+ operator
+= operator
- operator
-= operator
* operator
*= operator
/ operator
/= operator
~ operator

The operators listed above have special meaning when applied to matrices.

The assignment operators will modify an existing matrix, and can also be used directly with atom.transform. Other operators will create a new matrix.


matrix procs

See also:
matrix
matrix operators
turn proc (applied to a matrix)
matrix/proc
New
Add
Interpolate
Invert
Multiply
Scale
Subtract
Translate
Turn

Add proc (matrix)

See also:
matrix
matrix operators
matrix procs
+= operator
Format:
Add(Matrix2)
Args:
Matrix2: another matrix
Returns:
src

This adds Matrix2 to the current matrix.


Interpolate proc (matrix)

See also:
matrix
matrix operators
matrix procs
Format:
Interpolate(Matrix2, t)
Args:
Matrix2: Another matrix
t: The interpolation factor: from 0 (src) to 1 (Matrix2). Usually this is a value between 0 and 1.

Calculates and returns a new matrix between src and Matrix2. If t is 0.5, then the result will be exactly halfway between both matrices.

There are many ways to interpolate matrices. Whenever possible, DM will interpolate by doing scaling and/or shearing first, then rotation, then translation. This is done by trying to find the angle of rotation of each matrix first; a rotation of 180° is counted as a flip rather than a rotation.

It is not strictly necessary for t to be between 0 and 1. Using a value out of bounds will extrapolate a matrix, continuing the change as far as t.


Invert proc (matrix)

See also:
matrix
matrix operators
matrix procs
~ operator
Format:
Invert()
Returns:
src

This inverts the current matrix, if possible.

Not all matrices can be inverted. If it's not possible, the matrix is said to be degenerate. This happens if, for example, all of the values in the matrix are zero. A degenerate matrix will not be changed by this proc.


Multiply proc (matrix)

See also:
matrix
matrix operators
matrix procs
*= operator
Format:
Multiply(Matrix2)
or
Multiply(n)
Args:
Matrix2: another matrix
n: a number
Returns:
src

This multiplies the current matrix by Matrix2 or n. If the n format is used, this is just like scaling the whole matrix. If another matrix is multiplied, then it is like doing the two transformations in order: src, then Matrix2.

Multiplication of one matrix by another depends on the order. You may get a different result multiplying A * B vs. B * A.


Scale proc (matrix)

See also:
matrix
matrix operators
matrix procs
Format:
Scale(x,y)
Args:
x: The amount of scaling to do in the x direction
y: The amount of scaling to do in the y direction
Returns:
src

The matrix is scaled by the appropriate amounts.

If y is omitted, x is used for both. E.g., Scale(2) is equivalent to Scale(2,2).


Subtract proc (matrix)

See also:
matrix
matrix operators
matrix procs
-= operator
Format:
Subtract(Matrix2)
Args:
Matrix2: another matrix
Returns:
src

This subtracts Matrix2 from the current matrix.


Translate proc (matrix)

See also:
matrix
matrix operators
matrix procs
Format:
Translate(x,y)
Args:
x: The amount of scaling to do in the x direction
y: The amount of scaling to do in the y direction
Returns:
src

The matrix is translated (moved) by the appropriate amounts. The x and y offsets applied by translation are in pixels.

If y is omitted, x is used for both. E.g., Translate(2) is equivalent to Translate(2,2).


Turn proc (matrix)

See also:
matrix
matrix operators
matrix procs
turn proc (applied to a matrix)
Format:
Turn(angle)
Args:
angle: The angle of clockwise rotation, in degrees
Returns:
src

The matrix is rotated clockwise, by the angle given.


mutable appearance

See also:
appearance var (atom)
image objects
vars (mutable appearance)

All atoms and images have an appearance, which is an immutable object that can be shared by many atoms. Making changes to an object's appearance generates new appearances, many of which may be temporary. For high-performance games, this can be a drawback. The /mutable_appearance type exists so that you can make multiple changes to an appearance without creating all the temporary objects, then turn it into a regular immutable appearance when finished.

A new mutable appearance is created via new/mutable_appearance, and giving it an atom, image, or appearance as a source object. Assigning it to an object's appearance var will create a new immutable appearance.

Example:

mob/proc/GetAngry() var/mutable_appearance/ma = new(src) ma.color = rgb(51,255,51) // green ma.transform = matrix(2,0,0,0,2,0) // scale x2 appearance = ma

Reading certain vars, such as overlays, will create a temporary list object that can be modified easily. With regular appearances, making many changes to the overlays list results in a lot of churn.

The /mutable_appearance datum is technically a descendant of /image, but this is only for convenience, and should not be relied on for any other purpose as it is subject to change in future versions.


vars (mutable appearance)

Built-in mutable appearance vars:

mob/var
alpha
appearance
appearance_flags
blend_mode
color
density
desc
dir
filters
gender
icon
icon_state
invisibility
underlays
overlays
layer
luminosity
maptext
maptext_width
maptext_height
maptext_x
maptext_y
animate_movement
mouse_over_pointer
mouse_drag_pointer
mouse_drop_pointer
mouse_drop_zone var
mouse_opacity var
name
opacity
pixel_x
pixel_y
pixel_w
pixel_z
plane
render_source
render_target
screen_loc
suffix
text
transform
verbs
vis_flags

mob

See also:
atom
movable atoms
procs (mob)
vars (mob)
client

Mobs are "mobile objects" derived from /mob, which derives from /atom/movable. Human players are associated with a mob when they log on. Mobs are typically used for other "creature" types as well such as NPCs. This type is slightly more complex than objs since it can be attached to a client.

This example defines the mob type /mob/guzzler.

Example:

mob guzzler desc = "Mean, mad, and wicked bad."

procs (mob)

Built-in mob procs:

mob/proc
Bump
Click
Cross proc
Crossed proc
DblClick
Del
Enter
Entered
Exit
Exited
Login
Logout
MouseDown
MouseDrag
MouseDrop
MouseEntered
MouseExited
MouseMove
MouseUp
MouseWheel
Move
New
Read
Stat
Topic
Uncross proc
Uncrossed proc
Write

Login proc (mob)

See also:
Logout proc (mob)
client var (mob)
Format:
Login()
When:
Called when a player's client tries to connect to a mob. This is called by default from client.New(), when the player logs into the world.
Default action:
If the mob has no location, place it near (1,1,1) if possible. Change the player's stat object (client.statobj) to the mob.

One can typically tell if a player is connecting to a fresh mob versus reconnecting to an existing one by testing if the mob's location is null.


Logout proc (mob)

See also:
Login proc (mob)
client var (mob)
key var (mob)
Format:
Logout()
When:
Called when a player's client has disconnected from a mob. This happens in client.Del() when the player logs out of the world. It may also happen when the player switches from one mob to another.
Default action:
None.

One may wish to distinguish between a player who has disconnected from the game and one who is simply switching from one mob to another. In the case of a player switching to another mob, by the time Logout() is called, the original mob's key will be null, whereas the key will still be non-null in the case of a player disconnecting from the game.


vars (mob)

Built-in mob vars:

mob/var
alpha
appearance
appearance_flags
blend_mode
ckey
client
color
contents
density
desc
dir
filters
gender
group
icon
icon_state
invisibility
underlays
overlays
key
layer
luminosity
maptext
maptext_width
maptext_height
maptext_x
maptext_y
animate_movement
loc
mouse_over_pointer
mouse_drag_pointer
mouse_drop_pointer
mouse_drop_zone var
mouse_opacity var
name
opacity
parent_type
pixel_x
pixel_y
pixel_w
pixel_z
plane
render_source
render_target
see_infrared
see_invisible
see_in_dark
sight
suffix
tag
text
transform
type
vars
verbs
vis_contents
vis_flags
vis_locs
x
y
z

ckey var (mob)

See also:
ckey proc
key var (mob)
Default value:
null

This is the value of mob.key converted to canonical form (ie the form returned by the ckey() proc). Among other things, this could be used as a unique directory name in a server-side save file for storing player information. See the ckey() proc for an example.


client var (mob)

See also:
client
Default value:
null

This is a reference to a set of properties specific to the player. Therefore non-player mobs (NPCs) do not have a client (client = null).

Setting a mob's client connects that player's client to the mob.


group list var (mob)

See also:
Bump proc (movable atom)
list
Default value:
(empty list)

This is a list of mobs in the same group. By default, a mob will swap positions with another mob in its group if bumped. It is also possible to make verbs that are accessible only to members of the group.

The following example handles addition of somebody else to your group.

Example:

mob/verb/join(mob/M) usr.group.Add(M) // add M to usr's group view() << "[usr] joins [M]." mob/verb/disband(mob/M) usr.group.Remove(M) // remove M from group view() << "[usr] disbands [M]."

Note that group lists may be asymmetric. Mob A may have mob B in his group list, but mob B may or may not. It is up to you to define whether mobs are added into both lists or not.

Here is an example of a verb accessible to a group:

Example:

mob/verb/summon() set src in usr.group loc = usr.loc view() << "[usr] summons [src]."

key var (mob)

See also:
ckey var (mob)
client
key var (client)
Default value:
null

For player mobs (PCs) this is the value of the player's key. For non-player mobs (NPCs), this is the value of the "desired" key. This means that if a player with that key logs into the world, he will be connected to that mob (as opposed to a new one of type world.mob).

Setting the mob's key will cause a client with the same key to connect to the mob. Any other mob with the same key will lose it.

Key values are always compared in canonical form (ie the form returned by ckey()) so setting a mob's key to "Dan", "dan" are equivalent as far as controlling player linkage.


parent_type var (mob)

See also:
parent_type var

The default parent_type of /mob is /atom/movable.


see_in_dark var (mob)

See also:
luminosity var (atom)
see_infrared var (mob)
see_invisible var (mob)
sight var (mob)
view proc
Default value:
2

This determines how far the mob can see in the dark. The scale is just like luminosity: a value of 1 illuminates the mob and its location; 2 illuminates the immediate surrounds; and so on.


see_infrared var (mob)

See also:
infra_luminosity var (atom)
see_in_dark var (mob)
see_invisible var (mob)
sight var (mob)
view proc
Default value:
0

Setting this to 1 enables infravision, allowing the mob to see infrared objects in the dark.


see_invisible var (mob)

See also:
invisibility var (atom)
see_in_dark var (mob)
see_infrared var (mob)
sight var (mob)
view proc
Default value:
0

This is the maximum level of invisibility that the mob can see.


sight var (mob)

See also:
invisibility setting (verb)
invisibility var (atom)
see_in_dark var (mob)
see_infrared var (mob)
see_invisible var (mob)
view proc
Default value:
0

This controls which objects on the map the mob can see. The default value of 0 means that the mob can see all objects that are visible and lit. Different flags in this var can be set to extend or limit this range.

The following bit flags are encoded in mob.sight:

SEE_INFRA // can see infra-red objects SEE_SELF // can see self, no matter what SEE_MOBS // can see all mobs, no matter what SEE_OBJS // can see all objs, no matter what SEE_TURFS // can see all turfs (and areas), no matter what SEE_PIXELS// if an object is located on an unlit area, but some of its pixels are // in a lit area (via pixel_x,y or smooth movement), can see those pixels SEE_THRU // can see through opaque objects SEE_BLACKNESS // render dark tiles as blackness BLIND // can't see anything

Example:

usr.sight |= BLIND // turn on the blind bit usr.sight &= ~BLIND // turn off the blind bit usr.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS) // turn on several bits at once usr.sight &= ~(SEE_MOBS|SEE_OBJS|SEE_TURFS) // turn off several bits at once

SEE_PIXELS draws everything and then covers hidden turfs with blackness. It is supported in topdown maps only, not in other map formats. It does not mix well with other flags. In practice, SEE_PIXELS acts as if SEE_BLACKNESS, SEE_TURFS, SEE_OBJS, and SEE_MOBS are all turned on. That is, all atoms are drawn even on hidden tiles, and black squares are also drawn to cover them.

The black tiles rendered by SEE_BLACKNESS and SEE_PIXELS are drawn on the default plane 0.


obj

See also:
atom
movable atoms
procs (obj)
vars (obj)

There are two types of movable atoms: objs and mobs. The difference between them is that a mob can be attached to a human player, and is also typically used for NPCs and creatures. The obj type is a little bit simpler and is typically used for objects in the environment, items in inventory, etc.

Objects are derived from /obj, which derives from /atom/movable.

The following example defines the obj type /obj/scooper.

Example:

obj scooper desc = "Super pooper scooper."

procs (obj)

Built-in obj procs:

obj/proc
Bump
Click
Cross proc
Crossed proc
DblClick
Del
Enter
Entered
Exit
Exited
MouseDown
MouseDrag
MouseDrop
MouseEntered
MouseExited
MouseMove
MouseUp
MouseWheel
Move
New
Read
Stat
Topic
Uncross proc
Uncrossed proc
Write

vars (obj)

Built-in obj vars:

obj/var
alpha
appearance
appearance_flags
blend_mode
color
contents
density
desc
dir
filters
gender
icon
icon_state
invisibility
underlays
overlays
layer
luminosity
maptext
maptext_width
maptext_height
maptext_x
maptext_y
animate_movement
loc
mouse_over_pointer
mouse_drag_pointer
mouse_drop_pointer
mouse_drop_zone var
mouse_opacity var
name
opacity
parent_type
pixel_x
pixel_y
pixel_w
pixel_z
plane
render_source
render_target
suffix
tag
text
transform
type
vars
verbs
vis_contents
vis_flags
vis_locs
x
y
z

parent_type var (obj)

See also:
parent_type var

The default parent_type of /obj is /atom/movable.


operators

See also:
operator overloading

Operators are used extensively in DM to compute numerical values.

The DM operators are:

() . : / ::     // here . : / are path operators
[] . :
?[] ?. ?:
~ ! - ++ -- * &     // unary operators (* and & here are pointer operators)
**
* / % %%
+ -
< <= > >=
<< >>
== != <> ~= ~!
&
^
|
&&
||
?               // ternary a ? b : c
= += -= -= *= /= %= %%= &= |= ^= <<= >>= := &&= ||=
in

Each line has higher order of operations than the next. Operators within a line have equal precedence and therefore are processed from left to right as they occur in an expression. (Assignment, or operate-and-assign, are processed from right to left.)

Expressions of the form A #= B are shorthand for A = A # B except for ~= and :=.

Example:

var/N N = 0 // 0 N += 1+1*2 // 3 if(1 + 1 == 2) N = 2 // 2 if(N==2 && 1/2==0.5) N = 0.5 // 0.5

! operator

See also:
&& operator
operators
|| operator
Format:
!A
Returns:
1 if A is a false value (zero, an empty string, or null); 0 otherwise.

!= operator

See also:
> operator
< operator
<> operator
== operator
~= operator
~! operator
operators
Format:
A != B
Returns:
1 if A is not equal to B; 0 otherwise

This is identical to the <> operator.

To check if A and B are not equivalent, use the ~! operator.


% operator

See also:
%= operator
%% operator
operators
Format:
A % B
Returns:
The remainder of A / B, where both A and B are integers.

A % B is read "A modulo B", which stands for the remainder of A divided by B.

This operator only works with integer values, for legacy reasons. A and B are truncated to integers before the modulo operation. There are uses for the integer truncation, but if you don't want that and want the fractional modulo instead, you can now use the %% operator.


%% operator

See also:
% operator
%%= operator
operators
Format:
A %% B
Returns:
The remainder of A / B.

A %% B is read "A modulo B", which stands for the remainder of A divided by B.

This is a newer version of the % operator that supports all numbers, not just integers. It is equivalent to B * fract(A / B). The % operator does the same thing, but truncates A and B to integers first.


%%= operator

See also:
%% operator
operators
Format:
A %%= B

Set A equal to A %% B. It is shorthand for A = A %% B.

A %% B is read "A modulo B", which stands for the remainder of A divided by B. This version of the operator works with fractional values for A and B.


%= operator

See also:
% operator
operators
Format:
A %= B

Set A equal to A % B. It is shorthand for A = A % B.

A % B is read "A modulo B", which stands for the remainder of A divided by B. A and B are truncated to integers before the modulo; use %%= instead to work with fractional values.


& operator

See also:
&= operator
operators
| operator
Format:
A & B
Returns:
The binary "and" of A and B.

A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

If A and B are lists, the result is a list that contains only items that were in both lists, in the order of list A.

If A is an icon or /icon datum, it is blended with B which can be either a color or another icon. This is identical to the + operator. Transparent areas in either icon will be transparent in the result.


& pointer operator

See also:
* operator (pointers)
operators
ispointer proc
Format:
&A
Returns:
A pointer to the var or list item A.

Sometimes it is desirable to have easy access to a var without knowing its name, or send multiple items back from a proc. To do this, you can create a pointer to that var. Then you can use the * operator to refer to the value inside the pointer, or even to assign a value to it.

This operator is also called the reference operator, since it creates a reference to a var that you can use elsewhere.)

Example:

var/a=3, b=4 var/p = &a world << *p // same as world << a *p = 5 // same as a = 5 var/list/L = list(1, 2, 3) var/list/pl = &L[2] *pl *= 10 // same as L[2] *= 10

If you want the compiler to recognize that the item in your pointer var should be a certain type, you can give the pointer var that same type. Hence in the example above, pl is defined as a /list.

You can also call procs this way. You can either wrap the pointer and the * operator in paretheses, like (*p).MyProc(), or you can skip the operator and just call p.MyProc() directly.

The same also applies to the list index operator []. If p = &list then you can use (*p)[index] or p[index] interchangeably.

Pointers can be made for any of these kinds of vars:

One advantage of pointers is that you can use them to alter a value in a suspended (sleeping) proc.

Note: When spawn() is used, the current proc is forked, where one keeps running and a copy is scheduled to run later. If any pointers to proc vars were created, they belong to the original proc (the one that keeps running), not to the fork.


&& operator

See also:
! operator
operators
|| operator
Format:
A && B
Returns:
True value if both A and B are true (neither zero, an empty string, nor null); the first false value otherwise

The first false value from left to right completes the evaluation (a practice known as short-circuiting). The return value is equal to the last argument to be evaluated.


&&= operator

See also:
&& operator
|| operator
||= operator
operators
Format:
A &&= B
Returns:
Value of (A && B) after it has been assigned to A. This expression can stand by itself; its result does not need to be assigned to anything else.

First A is evaluated. If its value is true, B will be evaluated and assigned to A. If A is false, B will not be evaluated and A will remain unchanged.

Note that this is slightly different from if(A) A = B if A is a complex expression such as list[index++], because the expression is only evaluated once.

This operator cannot be overloaded.


&= operator

See also:
& operator
operators
|= operator
Format:
A &= B

Set A equal to A & B. It is shorthand for A = A & B.

This is commonly used to turn off certain bitfields in a word.

Example:

usr.sight &= ~BLIND // turn off the blind bit

If A and B are lists, items in A that are not in B are removed.

If A is an /icon or /matrix datum, the datum will be changed rather than creating a new one and re-assigning it to A.


> operator

See also:
>= operator
< operator
== operator
operators
sorttextEx proc
Format:
A > B
Returns:
1 if A is greater than B; 0 otherwise.

If A and B are text strings, a case sensitive comparison is performed (like sorttextEx()).


>> operator

See also:
>> input operator
>> operator (savefile)
>> shift operator

>> input operator

See also:
>> operator (savefile)
file proc
Format:
F >> Var

Cause input to be read from a file into a variable. The file may be a savefile or a file object corresponding to a text file.


>> shift operator

See also:
>>= operator
<< shift operator
operators
Format:
A >> B
Returns:
The bits of A shifted right B times.

A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

Bits shifted below the 24 low bits are lost.


>>= operator

See also:
>> shift operator
<<= operator
operators
Format:
A >>= B

Set A equal to A >> B. It is shorthand for A = A >> B.


>= operator

See also:
> operator
< operator
== operator
operators
sorttextEx proc
Format:
A >= B
Returns:
1 if A is greater or equal to B; 0 otherwise.

If A and B are text strings, a case sensitive comparison is performed (like sorttextEx()).


< operator

See also:
<= operator
> operator
== operator
operators
sorttextEx proc
Format:
A < B
Returns:
1 if A is less than B; 0 otherwise.

If A and B are text strings, a case sensitive comparison is performed (like sorttextEx()).


<> operator

See also:
!= operator
> operator
< operator
== operator
operators
sorttextEx proc
Format:
A <> B
Returns:
1 if A is not equal to B; 0 otherwise

This is identical to the != operator.


<< operator

See also:
<< operator (savefile)
<< output operator
<< shift operator

<< output operator

See also:
<< operator (savefile)
output proc
browse proc
browse_rsc proc
file proc
ftp proc
image proc
link proc
load_resource proc
run proc
sound proc
Format:
A << B

Cause the value B to be output to any players connected to mobs specified in A.

B may be an image, sound, or text. A may be a mob, the whole world, or any list containing mobs.

Example:

usr << "Hi, [usr.name]" view() << "To all in view" world << "Hi everybody!" usr << 'giggle.wav' view() << image(/obj/Fireball,usr)

<< shift operator

See also:
>> operator
<<= operator
operators
Format:
A << B
Returns:
The bits of A shifted left B times.

A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

Bits shifted beyond the 24 low bits are lost.


<<= operator

See also:
>>= operator
<< shift operator
operators
Format:
A <<= B

Set A equal to A << B. It is shorthand for A = A << B.


<= operator

See also:
> operator
< operator
== operator
operators
sorttextEx proc
Format:
A <= B
Returns:
1 if A is less than or equal to B; 0 otherwise.

If A and B are text strings, a case sensitive comparison is performed (like sorttextEx()).


() operator

See also:
operators
procs
verbs

Parentheses may be used in expressions to change the order of operations. Whatever is inside a pair of parentheses will be evaluated first.

Example:

usr << 2 + 3 * 2 // 8 usr << (2 + 3) * 2 // 10

They are also used for calling procs or verbs, by placing the parentheses after the name of the proc. Any arguments that will be sent to the proc go inside the parentheses; multiple arguments are separated by commas, or the parentheses can be left empty if no arguments are sent. For the same reason, parentheses are also used when defining a new proc or verb and the arguments (if any) that will be used.

Example:

// Defining a new proc proc/Distance(x, y) // return straight-line distance from 0,0 return sqrt(x*x + y*y)

* operator

See also:
*= operator
+ operator
- operator
/ operator
operators
Format:
A * B
Returns:
The product of A and B.

If A is an icon, the result is a new icon with B (a number, color, or another icon) multiplied. This works with the /icon datum as well.

If A is a /matrix datum, the result is a new matrix. B can be a number (which scales the whole matrix) or another matrix. Multiplying two matrices together can have different results depending on the order.


* pointer operator

See also:
& pointer operator
operators
ispointer proc
Format:
*A
Returns:
The value pointed at by a pointer stored in A

When using the & operator to get a reference pointer, you can access the value it points to with this version of the * operator. This can also be used on the left-hand side of assignment operations, for instance *A = B or *X += Y, to store the result in the place the pointer indicates.

This operator is also called the dereference operator, since it takes a pointer reference and gives you the value within.)

Example:

atom/proc/PixelPos(px, py) // get an exact step position *px = (x-1) * 32 // this code assumes a 32x32 icon size *py = (y-1) * 32 atom/movable/PixelPos(px, py) // get an exact step position ..() *px += step_x // this code assumes a 32x32 icon size *py += step_y mob/verb/WhereAmI() var/X, Y PixelPos(&X, &Y) usr << "You are at [X],[Y] on level [z]"

Note: If you try to read to or write from a pointer reference that is no longer valid, such as to a var inside a proc that has ended, the read or write will fail silently; reading will return a null value. (An exception is pointers to list items. If the index is out of bounds, you will get the expected error.)


** operator

See also:
log proc
operators
Format:
A ** B
Returns:
A to the power of B.

Example:

usr << 2 ** 3 // outputs 8

*= operator

See also:
* operator
+= operator
-= operator
/= operator
= operator
operators
Format:
A *= B

Set A equal to A * B. It is shorthand for A = A * B.

If A is an /icon or /matrix datum, the datum will be changed rather than creating a new one and re-assigning it to A.


+ operator

See also:
* operator
+= operator
- operator
/ operator
Add proc (list)
operators
Format:
A + B
Returns:
If A is a number, returns the sum of A and B.
If A is null, returns B.
If A is a list, a new list is returned with B appended to the contents of A. If B is a list as well, its contents are appended rather than the list itself.
If A is a text string, returns a new string with A and B concatenated.
If A is an icon, returns a new icon with B (a color or another icon) added. Areas that are transparent in either icon are transparent in both; for more opacity use | (OR) instead. This works with the /icon datum as well.
If A and B are both /matrix datums, returns a new matrix with their components added together.

++ operator

See also:
+ operator
+= operator
-- operator
operators
Format:
++A // pre-increment
A++ // post-increment

The pre-increment has the value (A+1) and the effect of adding 1 to A.

The post-increment has the value (A) and has the effect of adding 1 to A.

Example:

var/A = 0 world << "A++ = [A++]" // outputs "A++ = 0" world << "++A = [++A]" // outputs "++A = 2"

+= operator

See also:
*= operator
+ operator
-= operator
/= operator
= operator
operators
Format:
A += B

Set A equal to A + B. It is shorthand for A = A + B.

If A is an /icon or /matrix datum, the datum will be changed rather than creating a new one and re-assigning it to A.


- operator

See also:
* operator
+ operator
-= operator
/ operator
Remove proc (list)
operators
Format:
A - B
-B
Returns:
If A is a number, returns A minus B.
If A is a list, a new list is returned with B removed from the contents of A. If B is a list as well, each of its contents are removed rather than the list itself.
If A is an icon, returns a new icon with B (a color or another icon) subtracted. Areas that are transparent in either icon are transparent in both. This works with the /icon datum as well.
If A and B are both /matrix datums, returns a new matrix with their components subtracted.

-- operator

See also:
++ operator
- operator
-= operator
operators
Format:
--A // pre-decrement
A-- // post-decrement

The pre-decrement has the value (A-1) and the effect of subtracting 1 from A.

The post-decrement has the value (A) and has the effect of subtracting 1 from A.

Example:

var/A = 0 world << "A-- = [A--]" // outputs "A = 0" world << "--A = [--A]" // outputs "A = -2"

-= operator

See also:
*= operator
+= operator
- operator
/= operator
= operator
operators
Format:
A -= B

Set A equal to A - B. It is shorthand for A = A - B.

If A is an /icon or /matrix datum, the datum will be changed rather than creating a new one and re-assigning it to A.


/ operator

See also:
* operator
+ operator
- operator
/ path operator
/= operator
operators
Format:
A / B
Returns:
A divided by B.

If A is an icon, the result is a new icon whose color values (except alpha) are divided by B, which must be a number. This works with the /icon datum as well.

If A is a /matrix datum, the result is a new matrix. B can be a number (which scales the whole matrix) or another matrix. Dividing by matrix B is the same as multiplyng by its inverse. That is, A / B is identical to A * ~B.


/= operator

See also:
*= operator
+= operator
-= operator
/ operator
= operator
operators
Format:
A /= B

Set A equal to A / B. It is shorthand for A = A / B.

If A is an /icon or /matrix datum, the datum will be changed rather than creating a new one and re-assigning it to A.


: operator

See also:
. operator
?. operator
?: operator
: path operator
operators

This is the runtime search operator. It is used to access a property (var or proc) of a var that is not explicitly prototyped. If the variable doesn't have the specified variable or proc, a runtime error occurs.

Example:

var/M M = usr M:name = "futz" // access a mob property from a non-mob var

The . operator behaves the same way, but it checks at compile time whether the property is available. If the var is assigned a value that isn't the correct type and doesn't have this property, a runtime error will still occur.

Note: You should prefer the . operator in most situations, because it's better to catch a problem in the compiler instead of at runtime.


:: operator

See also:
. path operator
/ path operator
: path operator
operators
call proc
initial proc
nameof proc
istype proc
Format:
::A
::A()
A::B
A::B() (proc reference, not a call; see below)

This is the scope operator. It has multiple uses.

Global var and proc disambiguation

::A is a shorthand for global.A, so if you have a local or object var with the same name this disambiguates to the global var. The same is true of :A() which will call global.A() with the arguments you give it.

Static var disambiguation

If A is a constant type and B is a static var, A::B refers to the static var. If you have a local var with the same name, this disambiguates to the static var. This is also the only case where A::B can be used as an Lvalue (modifiable expression).

Initial value

The most common use of the scope operator is to get the initial value for a var. If A::B isn't a static var, then it's equivalent to initial(A:B). If A is a constant type path, the compiler will go even further by compiling this expression as the actual initial value instead of doing a runtime lookup.

This can also be used when defining a var that overrides its parent, by using the parent_type keyword for A. Multiple parent_type levels can be chained together. Similarly, in a static var definition, type can be used for A the same way.

Example:

thing var/price = 60 better price = parent_type::price + 40

Proc reference

If B is a proc, then A::B() is a reference to the proc for type A, which can be used in call(). In this case the parentheses are just a cue for the compiler to know this is a proc reference; it doesn't actually call the proc. Currently, A must be a constant type for this usage.

Example:

thing proc/DoSomething() world << "Did a thing" better DoSomething() world << "Did a better thing" proc/Downgrade() var/thing/better/T = new // will print "Did a better thing" because T is /thing/better T.DoSomething() // deliberately calls /thing's original version; will print "Did a thing" call(T, /thing::DoSomething())()

:= operator

See also:
= operator
operators
Format:
A := B

This is the "assign into" operator. The value of B is evaluated, then A. If A is a datum that has an operator:= proc overloading this operator, then that proc will be called with A as its src and B as its only argument. The return value of the proc (which defaults to its src, the old value of A) is assigned into the var that holds A.

If A was not a datum, then B is assigned into the var as if this were an ordinary A = B assignment.

A common use of this operator might be to copy another datum. This is basically just "syntactic sugar" to make certain datums easier to work with, and is intended mainly for situations where you've overloaded the operator.


= operator

See also:
*= operator
+= operator
-= operator
/= operator
%= operator
|= operator
&= operator
^= operator
<<= operator
>>= operator
:= operator
||= operator
&&= operator
operators
Format:
A = B

Set A equal to B.

Note that this is not the same as the equality test (==), which tests if A is equal to B.

All assignment operators, including calculate-and-assign (such as the += operator), can be chained together, and they are evaluated in right-to-left order. Therefore, a = b += c is a legal statement. It is equivalent to adding b and c, storing the result in b, then setting a to use the new value of b. (a = b) += c will, on the other hand, set a to equal b, then add c to a and store the result in a; b is never changed.


== operator

See also:
!= operator
>= operator
<= operator
~= operator
~! operator
operators
Format:
A == B
Returns:
1 if A and B are equal; 0 otherwise

Note that this is not the same as the assignment operator (=), which sets A equal to B.

To check if A and B are equivalent, use the ~= operator.


. operator

See also:
: operator
?. operator
?: operator
operators

This is used to access the procs and vars of a prototyped object. The variable need not actually contain a value with the specified type, but must at least be a type with the specified variable or a runtime error will occur, causing the proc to crash.

Example:

var/mob/M = new M.name = "futz" // assign 'name' mob var M.Move(0) // call 'Move()' mob proc

This is the same as the : operator, except that the compiler checks to see if the var type has this property, and throws a compiler error if not. It is good practice to use the . operator whenever possible, so more potential problems can be caught during compilation.

If . follows a proc call, a list lookup, or a complex expression where the type can't be known, it will act like : instead.


? operator

See also:
operators
Format:
Expr ? TrueExpr : FalseExpr

If Expr is true, this evaluates and returns TrueExpr. Otherwise, it evaluates and returns FalseExpr.


?. operator

See also:
. operator
: operator
?: operator
operators

This is used to access the procs and vars of a prototyped object. It is just like the . operator, but if the object is null, the access does not happen and there will be no runtime error. (A runtime error can still happen if the object is valid but is a different type that doesn't have the property available.)

When used in an expression to read a value or call a proc from a null object, the result of the expression is null. When used for assignment, the assignment will not happen, and the expression being assigned will not be evaluated, if the object is null.

Example:

var/mob/M // M is null by default M?.name = "futz" // assignment is skipped because M is null world << M?.name // M?.name reads as null because M is null M?.Move(loc) // call Move() mob proc; again nothing happens M = new M?.name = "futz" // assignment is made because M is valid now world << M?.name // outputs "futz" M?.Move(loc) // call Move() mob proc for M

When reading A?.B, it's roughly equivalent to A && A.B except that A is only evalulated once, even if it's a complex expression like a proc call. Making an assignment to A?.B is the same: A is evalulated only once, and if it's not null then an assignment is made to its B var.

For a version of this operator that doesn't check at compile time if the property is available, use the ?: operator instead.

If ?. is used after a proc call, a list lookup, or a complex expression where the type can't be known, it will act like ?: instead.


?: operator

See also:
. operator
: operator
?. operator
operators

This is used to access the procs and vars of an object. It is just like the : operator, but if the object is null, the access does not happen and there will be no runtime error. (A runtime error can still happen if the object is valid but the property is not available.)

When used in an expression to read a value or call a proc from a null object, the result of the expression is null. When used for assignment, the assignment will not happen, and the expression being assigned will not be evaluated, if the object is null.

Example:

var/mob/M // M is null by default M?:name = "futz" // assignment is skipped because M is null world << M?:name // M?:name reads as null because M is null M?:Move(loc) // call Move() mob proc; again nothing happens M = new M?:name = "futz" // assignment is made because M is valid now world << M?:name // outputs "futz" M?:Move(loc) // call Move() mob proc for M

When reading A?:B, it's roughly equivalent to A && A:B except that A is only evalulated once, even if it's a complex expression like a proc call. Making an assignment to A?:B is the same: A is evalulated only once, and if it's not null then an assignment is made to its B var.

This is identical to the ?. operator, except that ?. will check at compile time if the property is valid for the object type (if known). For this reason ?. is usually safer.


?[] operator

See also:
list
operators
[] operator
?. operator
?: operator

This is the null-conditional list index operator. It is used to access an element of a list, IF that list is not null. If the list is null, then the access will not happen and the index expression inside the brackets won't be evaluated. If this is the left-hand side of an assignment operator, such as list?[index] = rhs, then rhs is also not evaluated when the list is null.

Example:

var/list/good = list(5,6,7) var/list/bad var/idx = 1 // prints null because bad is null; idx is not changed world << json_encode(bad?[idx++]) // prints 5 because good is not null, and good[1] is 5; idx changes to 2 world << json_encode(good?[1]) idx = 1 // reset idx // bad is null, so idx does not advance and myproc() is not called bad?[idx++] = myproc() // good is not null, so idx advances after read, and myproc() is called good?[idx++] = myproc()

This operator cannot be overloaded, but overloads to the [] operator will apply to this operator as well.


[] operator

See also:
list
operators
?[] operator

This is used to access an element of a list.

Example:

var/L[2] // declares list of size 2 L[1] = 10 // assign first element

If you want to use a datum like a list, you can overload the operator by defining an operator[] proc for reading a value, and operator[]= for writing a value. Those overloads also apply if you use the null-conditional ?[] operator.


^ operator

See also:
^= operator
operators
Format:
A ^ B
Returns:
The binary "xor" of A and B.

A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

If A and B are lists, the result is a list containing items that are in either list but not both. list(1,2) ^ list(2,3) is equivalent to list(1,3). The items found only in A come first in the result, followed by any items found only in B.


^= operator

See also:
^ operator
operators
Format:
A ^= B

Set A equal to A ^ B. It is shorthand for A = A ^ B.

If A and B are lists, any items that are found in both lists are removed from A, and then any items found only in B are added to A.


in operator

See also:
list
operators
! operator
locate proc
input proc
Format:
A in List
Returns:
1 if A exists in List; 0 if not

This is a relatively safe way to check if an item is in a list, because the value of List is allowed to be a non-list value, such as null. Compare to List.Find(A) which will fail if List is not an actual list.

List can also be an atom, in which case A in List is equivalent to A in List.contents.

The in operator has a lower precedence than !, which can be a point of confusion. If you want to check if something is not in a list, it's a common mistake to try if(!A in List). Unfortunately the !A part is evaluated first and becomes 0 or 1, so you're really asking if 0 or 1 is in the list. The correct way to check if something is not in a list is to wrap the in operator and its operands with parentheses, as in if(!(A in List)).

Similarly, the assignment operators also have higher precedence than in, so has_thing = thing in src will not be interpreted as you might expect. Again the solution is to use parentheses, e.g. has_thing = (thing in src).

The in operator is also a modifier for some procs such as locate() and input().

Note: For associative lists there's a faster way to see if an item is in that list. The lookup of List[A] in an associative list is relatively fast, so if the associated value is always expected to be true (not null, 0, or an empty string), you can use List[A] instead of A in List in those situations.


path operators

See also:
. path operator
/ path operator
: path operator
procs
vars

A "path" in DM is a constant value that identifies a particular definition in the code tree (i.e. an object, procedure, or variable definition). An example of this is the default mob type for new players /mob.

Paths are used in two contexts. One is to "get to" a particular point in the code tree in order to modify the definition. The other is to reference a particular definition made elsewhere in the code tree. The syntax of a path is similar in both cases.

When you are making a definition, you simply put the path at the beginning of a line like this:

obj/clothes/gloves

That automatically creates that path in the code tree if it does not already exist. When starting at the beginning of the line (no indentation) there is no need to begin the path with '/', but that is perfectly acceptable.

When making definitions, DM equates the path separator '/' with indentation, so the above example is really just a more compact way of writing:

obj clothing gloves

One generally uses indentation when you have several things to define with a common parent path:

obj clothing gloves sandals

An important element of DM is that you can get to the same path in the code tree from multiple places in the source code. For example, given the above definition of gloves and sandals, you could modify a property of one of them from somewhere else using any path syntax you like:

obj/clothing/sandals name = "Winged Sandals"

While that was not a useful thing to do in this case, it can be a very powerful tool when organizing source code in large projects. Also note that the use of "/" can save your source code from getting too deeply indented, which may sound mundane, but which is quite important!

The above examples used paths to make definitions. The other time when you use paths is when you need to refer to a particular definition. Creation of an object is one example:

mob/Login() if(length(contents) == 0) //poor fellow has nothing //create sandals in his contents list new /obj/clothing/sandals (src) return ..()

Another common use of paths is to declare the data type of a variable. In DM, variable types do not affect what type of data the variable may contain—variables that you define may contain any type of value. Instead, the variable type affects what properties of the data you can attempt to access.

The following example defines variables for clothing that is occupying various positions on the body.

mob var/clothing feet hands torso

Since there were several variables of the same type, they were grouped under var/clothing. It can be done any number of ways, depending on the situation. The same path syntax applies to variable definitions as it does to anything else. This example produces the same effect:

mob/var/clothing/feet mob/var clothing hands torso

Provisos

Just do not make a mistake like the following:

mob/var /clothing/feet

Beginning a path with '/' effectively ignores whatever indentation may precede it. That is why it is called an absolute path. The above example would therefore be the same as the following, which is not what you want:

mob/var //empty variable definition clothing/feet //definition of object type /clothing/feet

On a related note, parameter definitions in procedures should not begin with a "/".

mob/Move(atom/Dest) //correct src << "Moving to [Dest.x],[Dest.y]." return ..() mob/Move(var/atom/Dest) //ok mob/Move(/atom/Dest) //WRONG

Essentially, "var/" is prepended to each entry in the parameter list.


/ path operator

See also:
. path operator
: path operator

This is used to delimit paths in the DM code tree. A path beginning with '/' is an absolute path (which is independent of where in the code it is used). Otherwise, a path is relative, meaning it starts from the current position in the code.

The following example uses a path in the code tree to define the type of object to create when leaving a corpse behind.

Example:

obj var poison nutrition corpse frog nutrition = 10 spider nutrition = 6 poison = 5 mob var corpse = /obj/corpse Die() new corpse(src.loc) //create the corpse here del src spider corpse = /obj/corpse/spider frog corpse = /obj/corpse/frog

: path operator

See also:
. path operator
/ path operator

The colon operator may be used as a short-cut when specifying a path in the DM code tree. Instead of specifying the full path, you can insert a colon and the compiler will search down in the tree with the node you specify. This is known as a "downward" search. You should only use it when the target node is unique.

The following example demonstrates the principle but it obviously doesn't save much typing!

Example:

world mob = :player //short-cut to /mob/player mob/player Login() src << "Welcome, [name]."

. path operator

See also:
/ path operator
: path operator

The dot operator may be used as a short-cut when specifying a path in the DM code tree. Instead of specifying the full path, you can start a path with a dot and the compiler will search up in the code tree for the following node. This is known as a relative path with an "upward" search.

Here are the beginnings of a text MUD that allows you to walk around between rooms using the arrow keys. The links between rooms are created in this example by referencing the object type of the destination room. Since there could potentially be a lot of rooms, they are grouped into sub-classes, and to avoid lengthy type paths such as /area/Village/Square, they are referenced using a relative path from the point of reference.

Example:

area var/area north_exit south_exit east_exit west_exit Entered(O) O << name return ..() Castle Main_Gate north_exit = .Castle_Entryway south_exit = .Moat_Bridge Castle_Entryway south_exit = .Main_Gate Moat_Bridge north_exit = .Main_Gate south_exit = .Village/Guard_Post Village Guard_Post north_exit = .Castle/Moat_Bridge south_exit = .Square Square north_exit = .Guard_Post //handle movement client/Move(Dest,Dir) var/area/room = usr.loc if(istype(room)) //in a room switch(Dir) if(NORTH) Dest = room.north_exit if(SOUTH) Dest = room.south_exit if(EAST) Dest = room.east_exit if(WEST) Dest = room.west_exit return ..() //set the starting position for new logins mob/Login() if(!loc) Move(locate(/area/Castle/Main_Gate)) return ..()

| operator

See also:
& operator
operators
|= operator
Format:
A | B
Returns:
The binary "or" of A and B.

A and B must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

If A and B are lists, the result is a list containing items that are in either list. list(1,2) | list(2,3) is equivalent to list(1,2,3). The items from A come first in the result, followed by any extra items from B.

If A is an icon or /icon datum, it is blended with B which can be either a color or another icon. Unlike the + or & operation, the result is transparent only in places where both icons were transparent.


|= operator

See also:
&= operator
operators
| operator
Format:
A |= B

Set A equal to A | B. It is shorthand for A = A | B.

This is commonly used to turn on certain bitfields in a word.

Example:

usr.sight |= BLIND // turn on the blind bit

If A and B are lists, any items in B that are not already in A are added to A.

If A is an /icon or /matrix datum, the datum will be changed rather than creating a new one and re-assigning it to A.


|| operator

See also:
! operator
&& operator
operators
Format:
A || B
Returns:
true value if either A or B is true (neither zero, an empty string, nor null); false value otherwise

The first true value from left to right completes the evaluation (a practice known as short-circuiting). The entire expression takes the value of the last argument to be evaluated.


||= operator

See also:
|| operator
&& operator
&&= operator
operators
Format:
A ||= B
Returns:
Value of (A || B) after it has been assigned to A. This expression can stand by itself; its result does not need to be assigned to anything else.

First A is evaluated. If its value is false, B will be evaluated and assigned to A. If A is true, B will not be evaluated and A will remain unchanged.

Note that this is slightly different from if(!A) A = B if A is a complex expression such as list[index++], because the expression is only evaluated once.

This operator cannot be overloaded.


~ operator

See also:
operators
Format:
~ A
Returns:
The binary "not" of A.

A must be between 0 and 2**24 - 1, giving an effective width of 24 bits.

If A is a /matrix datum, the result is a new matrix which is the inverse of A.


~= operator

See also:
~! operator
== operator
!= operator
operators
Format:
A ~= B
Returns:
1 if A and B are equivalent; 0 otherwise

Equivalence is a looser version of equality:

To check if A and B are equal, use the == operator.


~! operator

See also:
~= operator
== operator
!= operator
operators
Format:
A ~! B
Returns:
1 if A and B are not equivalent; 0 otherwise

Equivalence is a looser version of equality. See the ~= operator for more information.

To check if A and B are not equal, use the != operator.


operator overloading

See also:
datum
operators

DM allows you to overload most of the operators it uses when working with datums and other objects. This means that A + B can call a proc defined under A instead, with B as an argument, and the return value of that proc would be the result.

The proc name for an overloaded operator is "operator" followed immediately by the operator itself, such as operator* to override the multiplication operator. A * B will call A.operator*(B) if the proc is available.

Example:

complex // complex number a+bi var/a as num var/b as num New(_a,_b) a = _a b = _b proc/operator+(complex/C) if(istype(C)) return new/complex(a+C.a, b+C.b) if(isnum(C)) return new/complex(a+C, b) return src proc/operator+=(complex/C) if(istype(C)) a += C.a b += C.b else if(isnum(C)) a += C

The following operators may be overloaded:

OperatorsProcNotes
Arithmetic and binary (return new value)
A + BA.operator+(B)
A - BA.operator-(B)
-AA.operator-()Same proc as subtraction, but has no arguments
A * BA.operator*(B)
A / BA.operator/(B)
A % BA.operator%(B)
A %% BA.operator%%(B)
A ** BA.operator**(B)
A | BA.operator|(B)
A & BA.operator&(B)
A ^ BA.operator^(B)
~AA.operator~()
A << B (shift)A.operator<<(B)
A >> B (shift)A.operator>>(B)
A << B (output)A.operator<<(B,A,window)
world.operator<<(B,target,window)
Ignores return value
..() falls back on world proc, then default behavior
A >> B (input)A.operator>>(null,A)
world.operator>>(null,source)
Return value is assigned to B
..() falls back on world proc, then default behavior
Comparisons (return true or false)
A ~= BA.operator~=(B)
A ~! BA.operator~!(B)
A < BA.operator<(B)
A >= BA.operator>=(B)
A > BA.operator>(B)
A <= BA.operator<=(B)
Assignments with side effects (return value defaults to src)
A += BA.operator+=(B)
A -= BA.operator--(B)
A *= BA.operator*=(B)
A /= BA.operator/=(B)
A %= BA.operator%=(B)
A %%= BA.operator%%=(B)
A |= BA.operator|=(B)
A &= BA.operator&=(B)
A ^= BA.operator^=(B)
A <<= BA.operator<<=(B)
A >>= BA.operator>>=(B)
A := BA.operator:=(B)
++AA.operator++()
--AA.operator--()
A++A.operator++(1)
A--A.operator--(1)
List access
A[idx]A.operator[](idx)Used for reading a list value
A[idx] = BA.operator[]=(idx, B)Used for writing a list value; ignores return value
Other
turn(A, B)A.operator_turn(B)
"[A]"A.operator""()Specifies a custom way for converting A to text (see notes below)

Some operators cannot be overloaded. The = operator for direct assignment is one. The ! operator is another. The == and != operators measure equality and can't be overloaded, but ~= and ~! for equivalence can be. It would also be meaningless to override the ternary ? : operator pair, and the . and : family of operators for accessing vars and procs.

Comparison operators come in opposing pairs: ~= vs. ~!, < vs. >=, > vs. <=. You only need to override one operator from each pair; DM is smart enough to know that !(A ~= B) is the same as A ~! B.

By the same logic, you don't have to define the assign-with-side-effect operators like += if you don't want to. For instance if you override + but not +=, then A += B will be handled internally as A = A + B, which means the value of A after the statement may be a different datum than A was before. The value of A can also change if you do overload += but the proc returns a value other than null; its return value will be the new A.

If an overloaded proc is not available for an operator you try to use on a datum, a runtime error may result.

The output and input operators are given special treatment. If no overload is defined for the current left-hand-side value, the overload proc is looked up under world instead. The world overload proc is also a fallback if ..() is called, and after that ..() does the default behavior. These procs are always called with multiple arguments, to distinguish them from bitwise shift operators. The output version gets a third argument when the result output() is sent, since that can include a window reference.

Example:

// Send an effect to a player or list of players proc/DoEffect(target, effect/E) if(istype(target, /list)) for(var/i in target) DoEffect(i, E) return if(target == world || target == world.contents) for(var/client/C) DoEffect(C, E) if(istype(target, /client)) DoEffect(target:mob) if(istype(target, /mob)) if(target:client) ... // do something here to show the effect world/proc/operator<<(out, target) if(istype(target,/savefile)) return ..() // always save normally if(istype(out, /effect)) DoEffect(target, out) else ..()

The list access operators are a special case as well, because reading to a list and writing to it are different things, so there are two procs for the purpose. The [] overload is for reading, and []= is for writing.

There is also now an overload for converting a datum to text. By having operator"" return a text string, that text will automatically appear anywhere you embed the datum in a string, use json_encode() on the datum, or many other situations. It won't work for atoms being sent directly to output (e.g., world << obj) or other skin controls because the client has special handling for these situations and the client isn't given any info about the overloaded text. Likewise, the overloaded text won't appear for objects in an input() prompt list, which is also handled mainly on the client. Despite these limitations, the text overload offers greater flexibility.


procs

See also:
vars (procs)
arguments (proc)
procs (area)
procs (mob)
procs (obj)
procs (turf)

Procs may be derived from /proc. These procs are "global", in that they can be called anywhere in the code.

Example:

proc/poof() world << "POOF!"

The proc poof() may now be called anywhere in the code.

Procs may also be attached to objects by defining them under the appropriate object/proc subnode. Currently DM allows procs to be defined or overridden for /mob, /obj, /turf, /area, world, and /client, as well as for datum objects derived from /. Predefined procs are discussed under the "procs" entry for the object type.

Example:

mob/proc/poof() world << "POOF!"

This can be called by a mob var M, using M.poof().

Return types

It is possible to define what type of value a proc is expected to return, by following its definition with an as clause. This can be a type path, such as as /mob/player, or a more intrinsic type like as num or as list.

Example:

mob/monster var/mob/player/target proc/GetTarget() as /mob/player if(!target) // find a /mob/player in view target = locate() in view(src) return target

Currently the only purpose for using the as clause is for situations where the compiler needs to infer the type of an expression. Mainly this applies to the . and ?. operators in an expression such as GetTarget()?.Attack(src). Giving GetTarget() a return type allows the compiler to check if Attack() is a valid proc for /mob/player. Otherwise, the . and ?. operators act like : and ?:, respectively; the compiler won't do any checking to see if Attack() is valid.


. proc

See also:
.. proc
Format:
.(Args)
Returns:
The return value of the current proc.
Args:
The arguments to pass to the new invocation of the current proc. This defaults to current arguments.

Call the current proc. A proc that calls itself is said to be recursive.

Example:

proc/factorial(N as num) if(N<=0) return 1 return .(N-1)*N

This computes the factorial N! by calling itself recursively.


.. proc

See also:
. proc
Format:
..(Args)
Returns:
The return value of the parent proc.
Args:
The arguments to pass to the parent proc. This defaults to the arguments to the current proc.

If object O is derived from object P, P is called the parent of O. If a proc (or verb) is defined in both O and P, O can call P's version by using ..().

Example:

mob P verb/history() world << "P" O history() world << "O" ..() // call P.history()

Here O is derived from P. When P calls "history", his name is displayed. When O calls "history", his name is displayed, followed by the name of his parent, P.

If O overrides the same proc more than once, ..() will search for the previous version and use that. For instance, you could have two O.history() procs; the second overrides the first, but the original could still be called via ..(). The original in turn could call ..() to reach P.history(). Overriding the same proc more than once in the same type should be avoided wherever possible, because it incurs extra overhead, it makes the code harder to read, and it isn't always clear which one gets called first. (Usually, the only time you'll want this to happen is when using libraries.)

..() can also be used for predefined procs.

Example:

mob/Move() // override proc world << "moving..." return ..() // call default

This proc will print "moving..." whenever the mob moves.


ASSERT proc

See also:
CRASH proc
DEBUG definition
stddef.dm file
Format:
ASSERT(expression)
Args:
expression: an expression which should always be true

This is used to make a sanity check. If the given expression is false, the current procedure crashes, generating diagnostic debugging output, which includes the expression, a stack dump, and so forth.


CRASH proc

See also:
ASSERT proc
DEBUG definition
Format:
CRASH(msg)

Crashes the current procedure, displaying the specified message and generating diagnostic debugging output, such as a stack dump.


abs proc

Format:
abs(A)
Returns:
The absolute value of A.
Args:
A: A number.

Example:

usr << abs(1) // outputs 1 usr << abs(-1) // outputs 1

addtext proc

See also:
+ operator
Format:
addtext(Arg1,Arg2,...)
Returns:
A text string with the arguments concatenated.
Args:
Any number of text strings.

This instruction returns text containing the first argument followed by the second, followed by the third, etc. The arguments may be constants or variables containing text.

Example:

var/T T = "1" T = addtext(T,"*1 = ",T) // T = "1*1 = 1" world << "The answer is: [T]"

This instruction exists primarily for backwards-compatibility. You can accomplish the same thing with the + operator or by using embedded expressions.


alert proc

See also:
input proc
Format:
alert(Usr=usr,Message,Title,Button1="Ok",Button2,Button3)
Returns:
Selected button

This sleeps the current proc until the user clicks one of the named buttons. As with input(), the first argument may be entirely left out.

Example:

mob/verb/self_destruct() alert("Prepare to die.") del usr

A slightly more complicated example provides the user with a choice in the matter:

Example:

mob/verb/self_destruct() switch(alert("Would you like to die?",,"Yes","No","Maybe")) if("Yes") del usr if("No") usr << "You have second thoughts." if("Maybe") usr << "You flip a coin..." if(rand(0,1)) usr << "Heads -- you lose." del usr else usr << "Tails -- you win!"

animate proc

See also:
vars (atom)
Format:
animate(Object, var1=new_value1, var2=new_value2, ..., time, loop, easing, flags, delay)
animate(var1=new_value1, var2=new_value2, ..., time, easing, flags)
animate(Object)
Args:
Object: The atom, image, or client to animate. (Leave out to do a following animation step on the same object.)
var1=new_value1, var2=new_value2, ...: Vars to change in the animation step.
time: Time of this step, in 1/10s. (may be a named argument)
loop: Number of times to show the animation, or -1 to loop forever (may be a named argument)
easing: The "curve" followed by this animation step (may be a named argument)
flags: Flags that impact how the animation acts (may be a named argument)
delay: Delay time for starting the first step in an animation chain (may be negative; may be a named argument)

This proc creates an animation sequence that will be displayed to players. Starting with an atom or image, you can change one or more vars that affect its apprearance. This change will take place immediately, but will be displayed to users as a gradual change over a period of time. The actual interpolation between frames is all done on the client.

If the Object argument is left out, a new animation step will be created for the previously used animation seqeunce. If all other arguments are left out, this is tantamount to saying you want to start a new animation that does nothing, effectively ending the animation entirely.

Example:

mob/proc/GrowAndFade() // expand (scale by 2x2) and fade out over 1/2s animate(src, transform = matrix()*2, alpha = 0, time = 5) obj/spell/proc/Spin() // cast a spell on a monster: make the icon spin // this animation takes 3s total (6 ticks * 5) animate(src, transform = turn(matrix(), 120), time = 2, loop = 5) animate(transform = turn(matrix(), 240), time = 2) animate(transform = null, time = 2)

The following vars will animate smoothly:

These vars can be changed, but will change immediately on each step rather than smoothly:

Other vars may apply:

For convenience, you can use an associative list, appearance, or mutable appearance in place of the appearance vars. You can use appearance itself as a name for this argument, or leave the argument unnamed.

Easing

Animation doesn't have to be strictly linear. Some changes look much better if they follow a curve. A cubic curve, for instance, will start slow, accelerate very quickly in the middle, and slow down again at the end. A sine curve could be used with a flip transformation to make a coin appear to spin. A text bubble can jump into place and bounce a little before it settles. The choice of curve you use is called easing, and you have several good choices to pick from.

LINEAR_EASING
Default. Go from one value to another at a constant rate.
SINE_EASING
The animation follows a sine curve, so it starts off and finishes slowly, with a quicker transition in the middle.
CIRCULAR_EASING
Similar to a sine curve, but each half of the curve is shaped like a quarter circle.
QUAD_EASING
A quadratic curve, good for gravity effects.
CUBIC_EASING
A cubic curve, a little more pronounced than a sine curve.
BOUNCE_EASING
This transitions quickly like a falling object, and bounces a few times.
Uses EASE_OUT unless otherwise specified.
ELASTIC_EASING
This transitions quickly and overshoots, rebounds, and finally settles down.
Uses EASE_OUT unless otherwise specified.
BACK_EASING
Goes a little bit backward at first, and overshoots a little at the end.
JUMP_EASING
Jumps suddenly from the beginning state to the end. With the default or EASE_OUT, this happens at the end of the time slice. With EASE_IN, the jump happens at the beginning. With both flags set, the jump happens at the halfway point.

These can be combined with EASE_IN or EASE_OUT using the | operator, to use just the first or last part of the curve.

Example:

obj/coin/proc/Spin() var/matrix/M = matrix() M.Scale(-1, 1) // flip horizontally animate(src, transform = M, time = 5, loop = 5, easing = SINE_EASING) animate(transform = null, time = 5, easing = SINE_EASING) obj/speech_bubble/New(newloc, msg) icon = 'bubble.dmi' var/obj/O = new O.maptext = msg O.maptext_width = width O.maptext_height = height overlays = O // start below final position and jump into place pixel_z = -100 alpha = 0 animate(src, pixel_z = 0, alpha = 255, time = 10, easing = ELASTIC_EASING)

Some easing functions may overshoot one line or the other, so it's fully possible to have a pixel_w value, for instance, animate from 0 to 100 but actually end up briefly outside of that range during the animation.

Flags

Any combination of these flags may be used for animation (use + or | to combine them):

ANIMATION_END_NOW
Normally if you interrupt another animation, it transitions from its current state. This flag will start the new animation fresh by bringing the old one to its conclusion. It is only meaningful on the first step of a new animation.
ANIMATION_LINEAR_TRANSFORM
The transform var is interpolated in a way that preserves size during rotation, by pulling the rotation step out. This flag forces linear interpolation, which may be more desirable for things like beam effects, mechanical arms, etc.
ANIMATION_PARALLEL
Start a parallel animation sequence that runs alongside the current animation sequence. The difference between where the parallel sequence started, and its current appearance, is added to the result of any previous animations. For instance, you could use this to animate pixel_y separately from pixel_x with different timing and easing. You could also use this to apply a rotational transform after a previous animation sequence did a translate. (When using this flag, the src var may be included, but it is optional.)
ANIMATION_RELATIVE
The vars specified are relative to the current state. This works for maptext_x/y/width/height, pixel_x/y/w/z, luminosity, layer, alpha, transform, and color. For transform and color, the current value is multiplied by the new one. Vars not in this list are simply changed as if this flag is not present. (If you supply an appearance instead of individual vars, this flag is meaningless.)
ANIMATION_CONTINUE
This flag is equivalent to leaving out the Object argument. It exists to make it easier to define an animation using a for loop. If Object differs from the previous sequence, this flag will be ignored and a new sequence will start.
ANIMATION_SLICE
Following a series of animate() calls, you can view just a portion of the animation by using animate(object, delay=start, time=duration, flags=ANIMATION_SLICE). The loop parameter may optionally be included. The delay is the start time of the slice, relative to the beginning of all the active animations on the object. (That is, earlier animations that have concluded will not be included.) You can call the proc again with a different slice if you want to see a different portion of the animation. A negative value for time will remove the slice and finish any existing animations.

Filters

Filters can be animated too. If you want to animate a filter, you need to specify the filter to be animated. If the last call to animate() used the same object as this filter, or a different filter for that object, then this will be treated as a new step in the same animation sequece. Likewise, if the last animate() call was to a filter, and this call is for the object that filter belonged to, again it will be treated as a continuation of the sequence.

Example:

atom/proc/BlurFade() filters += filter(type = "blur", size = 0) // Animating a filter of src animate(filters[filters.len], size = 5, time = 10) // Switching back to src to animate the next step animate(src, alpha = 0, time = 2.5)

arccos proc

See also:
arcsin proc
arctan proc
cos proc
turn proc
Format:
arccos(X)
Returns:
The inverse cosine of X in degrees.

Example:

mob/verb/test() usr << arccos(0) // 90 usr << arccos(0.707107) // 45 usr << arccos(1) // 0

arcsin proc

See also:
arccos proc
arctan proc
sin proc
turn proc
Format:
arcsin(X)
Returns:
The inverse sine of X in degrees.

Example:

mob/verb/test() usr << arcsin(0) // 0 usr << arcsin(0.707107) // 45 usr << arcsin(1) // 90

arctan proc

See also:
arcsin proc
arccos proc
tan proc
turn proc
Format:
arctan(A)
arctan(x, y)
Returns:
The inverse tangent of A in degrees; or for x,y, the polar coordinate angle.

When arctan is called with just one argument, the resulting angle can range from -90 to 90.

The two-argument form uses the polar angle. This angle starts at 0° for due east, and increases counter-clockwise from there. Therefore 1,0 has an arctangent of 0°, 0,1 is 90°, -1,0 is 180°, and so on. At point 0,0 the angle is undefined since it could be any angle, but arctan will return 0.

Example:

mob/verb/test() usr << arctan(0) // 0 usr << arctan(1) // 45 usr << arctan(sqrt(3)) // 60 // polar coordinates usr << arctan(3, 4) // 53.1301 usr << arctan(-1, 1) // 135 usr << arctan(0, -5) // 270

Here's another example, in which a rotating turret points to a target on another tile.

mob/turret proc/PointAt(atom/target) if(!target) return var/dx = target.x - x var/dy = target.y - y // turret's icon normally faces east transform = matrix().Turn(-arctan(dx, dy))

arglist proc

See also:
arguments (proc)
call proc
call_ext proc
list proc
Format:
arglist(List)
Args:
List: a list to be used as the arguments to a procedure

Normally, if you were to pass a list directly to a procedure, it would only come through as a singe argument to that procedure. In some cases, you might instead want the items in the list to become the arguments to the procedure. That is what arglist() achieves.

If the items in the list are associations, these are treated as named arguments. Each such list item is matched against the names of the procedure arguments and its associated value is assigned to that parameter.

Most built-in DM instructions do not support use of arglist(), but all user-defined procedures automatically support it. The built-in instructions which support named arguments will also support arglist().

The following example shows how to use arglist() with both positional parameters and named arguments. Both of these examples could be replaced by a much simpler direct call without need for a list to hold the arguments; this is just to illustrate the syntax.

Example:

proc/MyProc(a,b) usr << "MyProc([a],[b])" mob/verb/test() var/lst = list(1,2) MyProc(arglist(lst)) //MyProc(1,2) lst = list(b=2,a=1) //just to illustrate that order does not matter MyProc(arglist(lst)) //MyProc(b=2,a=1) --> MyProc(1,2)

arguments (proc)

See also:
named arguments (proc)
path operators
arglist proc
args var (proc)

The parameters to a proc are referred to as arguments. To define argument variables, place them inside the ()'s in the proc definition. A default value may be specified. Otherwise, arguments default to null.

Example:

proc/Sum(a,b) return a + b

Example:

proc/set_mob_desc(mob/M,desc="big and bad") M.desc = desc world << "The new desc for [M] is [desc]."

Note how the variable type may be specified. It is just like any other variable definition, except "var/" is implicit and does not need to be typed.


named arguments (proc)

See also:
New proc (atom)
arglist proc
arguments (proc)

The parameters passed to a procedure are called arguments. These may either be passed in positional order, or they can be passed as named arguments. Not all procedures are defined with the intention of supporting named arguments, so consult the documentation for the procedure in question first. (This is mainly an issue of whether the argument names might change in the future.)

The following example shows several ways of producing the same call to a procedure.

Example:

mob/proc/MyProc(a,b,c) src << "MyProc([a],[b],[c])" mob/verb/test() MyProc(1,2,3) //positional parameters MyProc(a=1,b=2,c=3) //named arguments MyProc(1,b=2,c=3) //positional and named arguments MyProc(c=3,a=1,b=2) //named arguments can come in any order

To prevent silent errors, named arguments that do not match any of the arguments of the procedure being called will generate a runtime error. This is somewhat different from the behavior of positional arguments in DM where it is perfectly acceptable to pass more arguments than were explicitly defined in the procedure.

As always, arguments that are not assigned in the call will simply be given the value null (or whatever default value is specified in the definition).

When an object procedure is overridden, the variable names in the new definition are the ones that get matched against named arguments in a call to that procedure. A procedure which is intended to support named arguments should therefore be defined with care so as to conform to the interface expected by users of the procedure. That doesn't stop you from changing that interface when overriding a procedure, but the normal case would be to preserve the argument names of the base procedure when overriding it.

The following example is not useful, but it illustrates a situation where a procedure is overridden so as to preserve the same argument names and positions. As mentioned above, you are not required to preserve either the names or positions, but that is usually what you want.

Example:

mob proc/MyProc(a,b,c) usr << "mob.MyProc([a],[b],[c])" mob/verb/test() MyProc(a=1,b=2,c=3) special_mob MyProc(a,b,c,d) if(d) ..() //pass in same order else ..(c,b,a) //pass in reverse order test() MyProc(a=1,b=2,c=3,d=0) //normal order MyProc(a=1,b=2,c=3,d=1) //reverse the order

This example merely used positional parameters in the call to ..(), but one can use named arguments there too if it is desirable.

The best time to use named arguments is when calling a procedure that takes a lot of optional parameters. You can just name the ones that you want to assign and leave the rest unspecified. Trying to do the same thing with positional parameters can be much more awkward–especially when the arguments you do want to assign are preceded by a number of ones that you don't care to assign. It's easy to lose your place in the list or to forget what it does.

Since named arguments involve a slight amount of extra overhead, one should avoid them in code that is highly cpu intensive due to being called many many times. Otherwise, code clarity may be a bigger priority.


ascii2text proc

See also:
entities (text)
text2ascii proc
Format:
ascii2text(N)
Returns:
A text string.
Args:
N: A number.

ASCII codes are numerical values corresponding to keyboard and special characters. Among other things, they are used to represent many symbols in HTML. This proc converts an ASCII code to its corresponding text representation.

Example:

T = ascii2text(65) // = "A"

BYOND now supports Unicode via UTF-8 encoding, so you can use the character code for any valid Unicode character, not just ASCII.


block proc

See also:
list
Format:
block(Start,End)
block(StartX,StartY,StartZ, EndX=StartX,EndY=StartY,EndZ=StartZ)
Returns:
The list of turfs in the 3D block defined by Start and End (inclusive).
Args:
Start: A turf to be the lower-left corner of the block.
End: A turf to be the upper-right corner of the block.
StartX, StartY, StartZ: XYZ coordinates of the lower-left corner of the block.
EndX, EndY, EndZ: XYZ coordinates of the upper-right corner of the block.

The following example shows how to loop over a block of turfs.

Example:

world maxx = 20 maxy = 20 mob/verb/block_test() var/turf/T for(T in block(locate(1,1,1), locate(10,10,1))) T.text = " "

In the version that uses coordinates directly instead of two turfs, you can leave any of the EndX, EndY, or EndZ values as null, and omit the last arguments entirely; they will default to using the corresponding StartX, StartY, or StartZ. Therefore this example is equivalent to the one above:

Example:

world maxx = 20 maxy = 20 mob/verb/block_test() var/turf/T for(T in block(1,1,1, 10,10)) T.text = " "

bounds proc

See also:
bound_x var (movable atom)
bound_y var (movable atom)
bound_width var (movable atom)
bound_height var (movable atom)
step_x var (movable atom)
step_y var (movable atom)
locs list var (movable atom)
obounds proc
Pixel movement
bounds var (client)
Format:
bounds(Ref=src, Dist=0)
bounds(Ref, x_offset, y_offset, extra_width=0, extra_height=0)
bounds(x, y, width, height, z)
Returns:
A list of atoms within the given bounding box.
Args:
Ref: A turf, obj, or mob.
Dist: A number (distance in pixels).
x_offset, y_offset: Shift to bounding box position (from Ref's bounding box)
extra_width, extra_height: Adjustment to bounding box size (from Ref's bounding box)
x, y, z: Lower left corner of bounding box in absolute coords; x=1,y=1 is lower left of map
width, height: Size of bounding box in absolute coords

To leave Ref out of the results, use obounds() instead.

Calling bounds() will default to bounds(src,0), if src is a turf, obj, or mob. This returns all turfs, objs, and mobs (including src) within src's bounding box.

Changing the distance will return all objects within that distance from the bounding box. E.g., bounds(turf,12) will show you everything within 12 pixels of that turf.

An object's bounding box can also be offset. bounds(src,-6,0) shows what src would touching if it moved 6 pixels west. bounds(turf,-12,-12,24,24) is equivalent to bounds(turf,12).

In the final form, bounds() can use absolute coordinates and does not need an object to be Ref. Absolute coordinates start at 1,1 at the lower left corner of the map, by tradition.


bounds_dist proc

See also:
bound_x var (movable atom)
bound_y var (movable atom)
bound_width var (movable atom)
bound_height var (movable atom)
step_x var (movable atom)
step_y var (movable atom)
bounds proc
Pixel movement
Format:
bounds_dist(Ref, Target)
Returns:
The distance, in pixels, between Ref's and Target's bounding boxes.
Args:
Ref: A turf, obj, or mob.
Target: A turf, obj, or mob.

The value returned by bounds_dist() is the number of pixels that the two objects would have to move closer together (if this is even possible, of course) to be touching but not overlapping.

A return value of 12 for instance means the two objects have a gap of 12 pixels between them.

A return value of 0 means the two objects are not overlapping, but their bounding boxes touch.

A return value of -2 means the two objects are overlapping by 2 pixels; they would have to move 2 pixels apart to separate.


break statement

See also:
continue statement
do proc
for loop proc
while proc
Format:
break
break Label

Terminate the loop with the given label. If no label is specified, the innermost loop containing the break statement is assumed.

Example:

obj/zapper verb/use() var/mob/M for(M in view()) if(!M.key) break if(!M) M = usr M << "ZAP!" del(M)

The zapper object kills the first mob it finds that doesn't belong to a player. If none can be found, it kills the user. Be careful! Note how this code takes advantage of the fact that the loop variable M will be null if the loop terminates normally.

For an example of how to use labeled loops, see the reference section for the continue statement.


browse proc

See also:
<< output operator
browse_rsc proc
file proc
link proc
run proc
output proc
Format:
usr << browse(Body,Options)
Args:
Body: html text, file, or null to close the browser.
Options: optional parameters

This sends the html text or file to the user and optionally displays it in the web browser. The default action is to use the embedded browser panel in the Dream Seeker window; specifying an alternate window name (see below) causes it to appear in a popup window. Passing in 'null' for the html text causes the browser panel or named window to be closed.

The option parameters should either be omitted or they should be in a text string of the following format: "window=name;file=name;display=1;
size=300x300;border=0;can_close=1;
can_resize=1;can_minimize=1;titlebar=1"

You may use commas (,), ampersands (&), or semicolons (;) as the delimiter. Any or all of the parameters may be specified and they may be included in any order.

General options

These control how to handle the text or file.

window
This is the name used to identify the popup window. It is not visible to the user. Multiple calls to browse() with the same window name overwrite previous contents of the same popup window. If window is not specified, the embedded browser panel will be used.
file
When this is unspecified, the client will store the generated html file in the user's byond "cache" directory with an appropriate name. If Body is a text string, the client will generate a unique name. If it is a file, it will use the name of the file. You can override this by setting this parameter. This is only useful when you need to reference the file later, typically in tandem with the display setting below.
display
This controls whether the browser actually displays Body in the web browser or not. If it is turned off (display=0), the text or file is simply sent to the user and expected to be referenced later. This might be useful, for instance, to first send an image to a user and then display a web page that uses that image: usr << browse('monster.png',"display=0") usr << browse("<img src=monster.png>A scary monster appears from the mist!") Note that this performs the same function as the browse_rsc proc (preserved for legacy reasons). It is a little more powerful because you can use it to send html text as well as files. In that case, you'll have to also supply the file=name argument so that you can reference the html text from within a later browse().

When display=0, all of the other arguments besides file are ignored.

Popup options

These control how the popup window initially appears. Setting these parameters for an existing popup window or the embedded browser has no effect.

border
This is the width of the border between the edges of the dialogue and the window content. The default value is 0, meaning that the entire window is filled with html content.
size
This is the size of the popup window in pixels. The format is WIDTHxHEIGHT.
can_close
This specifies whether the window should be closable. The default value is 1, which enables the standard "X" button for closing.
can_resize
This controls whether the window is resizable. The default value is 1, enabling resizing and maximizing.
can_minimize
This controls whether the window is minimizable. The default value is 1, enabling the standard minimization button.
titlebar
The default titlebar=1 enables the standard bar at the top of the window. Turning it off disables can_close and can_minimize.

Note also that many display options can be controlled through the html itself. For instance, to turn off the scrollbars, you can do: <body scroll=no>; to add a title, you can do: <head><title>My Title</title></head>; and so forth.

The following example displays a help page in a popup window.

Example:

var/const/help = {" <html> <head><title>Help!</title></head> <body> You are beyond help! </body> </html> "} client/verb/help() usr << browse(help,"window=help") You can use commands like output() and winset() to interact with popups. The name of the window is the same name you gave the popup, and the browser is "[windowname].browser".

Example:

client/verb/more_help() usr << output("You are still beyond help!", "help.browser")

browse_rsc proc

See also:
browse proc
Format:
usr << browse_rsc(File,FileName)
Args:
File: a resource file (such as an image)
FileName: name of file (if different from source file)

This sends the specified resource file to usr (or anybody else) and stores it in their cache directory with the specified name. In subsequent browse() output, you can then refer to that file.

If your world is always running on the internet, you can save yourself the trouble and simply link to the image files through a web server. However, if it may be played offline, you can compile in the resource files and manually send them to players with browse_rsc().

Note that no data is transmitted if it already exists in the user's cache, so there is little overhead in calling this every time you are about to use browse().

Example:

area var room_graphic = 'cozy_room.jpg' Enter(O) . = ..() //do default checks if(.) //if we got clearance to enter O << browse_rsc(room_graphic,"room.jpg") O << browse("<p><img src=room.jpg></p>[desc]")

call proc

See also:
arglist proc
call_ext proc
hascall proc
path operators
Format:
call(ProcRef)(Arguments)
call(Object,ProcName)(Arguments)
call(LibName,FuncName)(Arguments) (use call_ext() instead)
Args:
ProcRef: path of proc (/proc/MyProc)
Object: source of proc or verb
ProcName: name of proc or verb ("MyProc")
LibName: name of external library ("test.DLL")
FuncName: name of function in external library ("func")
Returns:
The return value of the proc being called.

This instruction exists in order to call procs dynamically, since the proc reference or name may be an expression rather than a hard-coded value. This may serve the same purpose as a "function pointer" in C programs.

The following examples do not demonstrate why you would want to do this, but the syntax is illustrated. The first one calls a specific procedure by using a path reference to that procedure.

Example:

/proc/MyProc(Arg) usr << "MyProc([Arg])" mob var MyProc = /proc/MyProc verb call_myproc() call(MyProc)("Hello, world!")

The next example calls an object procedure (or verb) by name, rather than by path.

Example:

mob proc Proc1(Arg) usr << "Proc1([Arg])" Proc2(Arg) usr << "Proc2([Arg])" verb call_proc(Proc in list("Proc1","Proc2")) call(src,Proc)("Hello, world!")

In prior versions, call() was also used to access third-party libraries (.DLL files on Windows, .SO files on Unix), but this has been moved to call_ext() for clarity.


call_ext proc

See also:
arglist proc
call proc
path operators
Byondapi
Format:
call_ext(LibName,FuncName)(Arguments)
Args:
LibName: name of external library ("test.DLL") (note: the .dll or .so suffix is not required)
FuncName: name of function in external library ("func"), which may have prefixes to describe the type of function
Returns:
The return value of the external library function.

This instruction exists in order to access third-party libraries (.DLL files on Windows, .SO files on Unix), as long as the one or more of the following conditions is met:

String version

The standard way of making external calls (and until version 515, the only way) uses strings for everything. Any arguments that are not strings are passed as empty strings instead. The call is prototyped in the DLL this way:

extern "C" char *func(unsigned int argc, char *argv[]);

The argc argument is a number of arguments, and argv is an array of the arguments themselves. The integer must be 32-bit.

As the library prototype is char**, the call_ext() arguments must be strings. Other types (like numbers) will be passed as the empty string ("") into the library function.

Example:

// test.dll, a win32 C++ library compiled in VC++:
#include <string.h>
// This is an example of an exported function.
// Windows requires __declspec(dllexport) to be used to declare public symbols
// The name of the function from within the dll may be compiler-dependent
// (in this case it will usually be "merge" or "_merge").
// Google "name decoration" for more information on this exciting topic.
extern "C" __declspec(dllexport) char *merge(int n, char *v[]) 
{
    static char buf[500]; 
    *buf=0;
    for(int i=0; i<n; i++) {
        strcat(buf,v[i]); // we should bounds-check but it's a stupid example!
    }
    return buf;
}
// DM code to use test.dll mob/verb/test() usr << call_ext("test.dll","merge")("fee","fi","fo") // returns "feefifo" // As with the other call() versions, arglist() may be used to do runtime arguments: mob/verb/argtest() var/L = list("fee","fi","fo") usr << call_ext("test.dll","func")(arglist(L)) // returns "feefifo"

The char * pointer returned by the library is expected to be cleaned up by the library when it's unloaded, or it can be cleaned up on a subsequent function call. BYOND makes a copy of the string when the function returns and does not need it after that.

Byondapi version

A newer and more flexible way of calling external libraries is now available, and it allows you to pass strings, numbers, and references, and also get other types of valus in return. This uses Byondapi and requires your external library to be compiled with the byondapi.h header file (if using C or C++). Byondapi also includes helpful C++ wrapper classes in separate files.

With Byondapi calls, the function name you use in call_ext() should be prefixed by byond: so that the engine knows what type of function it is. In your library, the call is prototyped like so:

extern "C" CByondValue func(u4c argc, CByondValue argv[]);

The u4c type is an unsigned 32-bit integer, defined in byondapi.h. CByondValue is also defined there. Interacting with a CByondValue structure requires the functions exported as part of Byondapi.

Example:

// test_byondapi.dll, a win32 C++ library compiled in VC++:
#include <byondapi.h>
#include <stdlib.h>
#include <string.h>

// a different take on the merge example above
extern "C" BYOND_EXPORT CByondValue merge(int n, CByondValue v[])
{
    CByondValue result;
    u4c buflen = 1024;  // initial size of buffer
    u4c totallen = 0;   // length of total string so far (not including trailing null)
    char *buf = (char*)malloc(buflen);

    if(!buf) {  // we couldn't allocate memory
        ByondValue_Clear(&result);
        return result;
    }

    for(int i=0; i<n; i++) {
        u4c len = buflen - totallen;    // # of bytes left in buffer
        bool success = Byond_ToString(v[i], buf+totallen, &len);
        // on success, len is filled with # of bytes written (including trailing null)
        if(success) {
            totallen += (len-1);
        }
        // if we failed but len > 0, it's the new size of the buffer we need
        else if(len) {
            len = (len + 1023) & ~1023; // round up to 1K increments
            char *newbuf = (char *)mallloc(len);
            if(!newbuf) {   // out of memory; stop here
                ByondValue_Clear(&result);
                return result;
            }
            memcpy(newbuf, buf, totallen+1);    // include trailing null in copy
            free(buf);
            buf = newbuf; buflen = len;
            --i;  // retry Byond_ToString() for this argument
        }
        // if we failed but len == 0, there was an error
        else {
            free(buf);
            ByondValue_Clear(&result);
            return result;
        }
    }
    ByondValue_SetStr(&result, buf);    // create a new internal string
    free(buf);  // free the buffer
    return result;
}

extern "C" BYOND_EXPORT CByondValue average(int n, CByondValue v[])
{
    CByondValue result;
    float total = 0.0f;
    int count = 0;
    for(int i=0; i<n; i++) {
        if(!ByondValue_IsNum(v[i])) continue;
        total += ByondValue_GetNum(v[i]);
        ++count;
    }
    if(count) ByondValue_SetNum(&result, total / count);
    else ByondValue_Clear(&result); // return null on failure
    return result;
}
// DM code to use test_byondapi.dll mob/verb/test() usr << call_ext("test_byondapi","byond:merge")("fee","fi","fo") // returns "feefifo" mob/verb/average() usr << call_ext("test_byondapi","byond:average")(1,6,8) // returns 5

You are of course allowed to mix different argument types, so they don't all have to be numbers or all strings. Your library code can use the Byondapi functions to interact with these values.

Other prefixes

For advanced users: on Windows, call_ext() uses the __cdecl convention by default. If you are designing or linking to a DLL that uses the __stdcall convention instead, you can inform call_ext() by prefacing the function name with the "@" symbol. E.g., call_ext("test.dll","@merge") would call a version of merge declared with the __stdcall convention. Likewise if you use the Byondapi version, you can use call_ext("test.dll","@byond:merge") or call_ext("test.dll","byond:@merge") (it doesn't matter which order the prefixes go in).


ceil proc

See also:
floor proc
round proc
trunc proc
fract proc
Format:
ceil(A)
Returns:
the ceiling of A
Args:
A: A number.

Returns the ceiling of A (the largest integer greater than or equal to A).

Example:

usr << ceil(1.45) // outputs 2 usr << ceil(-1.45) // outputs -1

ckey proc

See also:
ckeyEx proc
ckey var (mob)
savefile
Format:
ckey(Key)
Args:
Key: The player key to convert to canonical form.
Returns:
The key in canonical form. To do this, it strips all punctuation and space from the key and converts to lowercase. The result is still unique for each different key.

The result could be used as a unique directory name in a server-side save file. Each player could be stored in a separate directory. By converting to canonical form, possible problems resulting from punctuation (like the path delimiter '/') in the key would be avoided. If players are saved in stand-alone files, it could be equally useful for generating a unique file name.

Note that this may be used on any text string. It is not just limited to keys.

Example:

var/savefile/SaveFile = new("world.sav") proc/SavePlayer(mob/M) var/keydir = ckey(M.key) SaveFile.cd = "/players" SaveFile.cd = keydir M.Write(SaveFile) proc/LoadPlayer(mob/M) var/keydir = ckey(M.key) SaveFile.cd = "/players" if(!SaveFile.Find(keydir)) return 0 SaveFile.cd = keydir M.Read(SaveFile) return 1

This example defines two procs for saving and loading players to a server-side file. These could be called in mob.Login() and mob.Logout(). Notice that instead of calling SaveFile.Write(M), this example instead calls M.Write(SaveFile) directly. The difference is that in this example we did not want a new mob to be created when loading the player but instead wanted to load information into an existing mob.

In this example, the ckey() proc was used, but it would be more efficient to use mob.ckey, which is the same value precomputed.


ckeyEx proc

See also:
ckey proc
Format:
ckeyEx(Text)
Args:
Text: The text string to convert to case-sensitive canonical key form.
Returns:
The same text stripped of all punctuation and space. Unlike, ckey(), case is preserved as are the '-' and '_' characters.

The true canonical form of a key is in all lowercase, but occasionally, it is nice to preserve case when stripping a key (or other text) of any special characters.

Note: This proc used to be named cKey, like ckey but with a capital k. To avoid confusion it has been renamed, but old code will still compile with a warning.


clamp proc

See also:
min proc
max proc
Format:
clamp(Number, Low, High)
clamp(List, Low, High)
Args:
Number: A number (or null, treated as 0).
List: A list of numbers.
Low: The lowest value that can be returned.
High: The highest value that can be returned.
Returns:
The original Number, constrained between Low and High.
The original List, whose contents have all been clamped.

"Clamps" a number to a given allowable range from Low to High. If the number is already in that range, it is unchanged. Otherwise, the closer of Low or High is returned.

This is effectively equivalent to min(max(Number, Low), High), but with some slight differences. For one thing, clamp() is forgiving if you accidentally swap Low and High; it will just swap them back so Low is always lower. Also, because this is a single proc call it's slightly faster.

Example:

usr << clamp(5, 0, 10) // 5; it falls between 0 and 10 usr << clamp(-1, 0, 10) // 0; it is less than 0 usr << clamp(20, 0, 10) // 10; it is more than 10

The list format will accept a list in place of a number as the first argument, and it behaves as if you looped through the entire list and ran clamp() on each number or null value. Please note the original list will be modified. If you want to leave the original list alone, use the Copy() proc to pass a copy to clamp() instead.


cmptext proc

See also:
cmptextEx proc
Format:
cmptext(T1,T2,...)
Returns:
1 if all arguments are equal; 0 otherwise.
Args:
Any number of text strings to compare.

This instruction is NOT sensitive to case. It also ignores the \proper and \improper text macros. The case-sensitive version is cmptextEx().

Example:

if(cmptext("Hi","HI")) world << "Equal!" else world << "Not equal!"

This outputs "Equal!" since "Hi" and "HI" are the same, ignoring case.


cmptextEx proc

See also:
cmptext proc
Format:
cmptextEx(T1,T2,...)
Returns:
1 if all arguments are equal; 0 otherwise.
Args:
Any number of text strings to compare.

This instruction is sensitive to case. The case-insensitive version is cmptext().

Because identical text is internally combined to conserve memory, cmptextEx(T1,T2) is equivalent to (T1 == T2).

Example:

if(cmptextEx("Hi","HI")) world << "Equal!" else world << "Not equal!"

This outputs "Not equal!" since "Hi" and "HI" are different when taking case into account.

Note: This proc used to be named cmpText, like cmptext but with a capital T. To avoid confusion it has been renamed, but old code will still compile.


continue statement

See also:
break statement
do proc
for loop proc
while proc
Format:
continue
continue Label

Begins the next iteration of the loop with the given label. If no label is specified, the innermost loop containing the continue statement is assumed.

In a for(Init,Test,Inc) loop, the continue statement will jump to the Inc portion (if any) and move on to the conditional Test. In a for(item in list) loop, it will skip to the next item in the list. In a while or do-while loop, continue jumps to the condition in the while statement.

Example:

client/verb/who() var/mob/M usr << "Players:" for(M in world) if(M == usr) continue if(M.key) usr << M.key

This displays a list of players who have a mob in the world. The continue statement is used here to avoid including the user in the list. The same thing could have been achieved by using only the if statement. In more complicated situations, however, very long conditional expressions and deeply nested if statements can be avoided by using continue and its companion break.

Here is an example using a label to continue an outer loop from inside an inner one:

client/verb/loners() var/mob/M var/mob/G usr << "Loners:" finding_loners: for(M in world) for(G in world) if(M in G.group) continue finding_loners //found a loner usr << M.name

This displays a list of mobs who do not belong in anyone else's group. Notice the syntax for labeling a list. The name of the block is simply placed in the code followed by a colon and its contents are indented inside it.


copytext proc

See also:
splicetext proc
findtext proc
splittext proc
trimtext proc
Copy proc (list)
Format:
copytext(T,Start=1,End=0)
Returns:
A text string.
Args:
T: A text string.
Start: The text byte position in which to begin the copy.
End: The text byte position immediately following the last character to be copied.

Copy characters in T between Start and End. The default end position of 0 stands for length(T)+1, so by default the entire text string is copied.

Example:

pre = copytext("Hi there",1,3))// = "Hi" post = copytext("Hi there",4)) // = "there"

If the start or end position is negative, it counts backwards from the end of the string.

Example:

post = copytext("Hi there",-5)) // = "there"

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use copytext_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


cos proc

See also:
arccos proc
sin proc
tan proc
turn proc
Format:
cos(X)
Returns:
The cosine of X, where X is in degrees.

Example:

mob/verb/test() usr << cos(0) // 1 usr << cos(45) // 0.707... usr << cos(90) // 0

del proc

See also:
Del proc (datum)
garbage collection
refcount proc
Format:
del Object
Args:
Object: Any data object (datum, savefile, world, you name it)

Destroy an object and null out all references to it. Procs that are executing with src equal to that object are silently killed, causing execution to return to the caller. If that is not what you want, you should detach the proc from the source object by setting src to null.

When an object is deleted, its Del() procedure is called. Currently, if the Del() procedure does not execute the default action (by calling ..()), then the deletion of the object is aborted. You should not depend on this, as it may change. In other words, be sure to always call the default handler after doing your own stuff.

Example:

mob/Del() src << "Aaaaaaaah!" ..() mob/verb/self_destruct() del usr

While manual object deletion is useful in many cases, the search for live references to an object does take some time. The more active objects in the world, and the more variables in those objects, the longer the search will take. For larger projects, this search time can become significant. In these cases, as a best practice, manual deletion should be avoided by ensuring that all references to an object are taken care of when the need for object destruction arises. Objects that have no references are deleted automatically without the need for a search. See garbage collection for more details.


do proc

See also:
break statement
continue statement
for loop proc
while proc
Format:
do Statement while( E )

Execute Statement. If E is true (non-zero) do it over again. Continue until E is false (zero).

Statement may be a block of code or a single statement.

Example:

var/i = 3 do world << i-- while(i)

This outputs:

3 2 1

EXCEPTION proc

See also:
try and catch statements
throw statement
exception
stddef.dm file
Format:
EXCEPTION(value)
Args:
value: A text string (such as an error message) or other value identifying the exception.

This is used to create an /exception datum, and is shorthand for calling new/exception(value, __FILE__, __LINE__). The value you provide will be in exception.name.


fcopy proc

See also:
fcopy_rsc proc
shell proc
Format:
fcopy(Src,Dst)
Args:
Src: file to copy
Dst: new copy to make
Returns:
1 on success; 0 otherwise.

Src may be either a cache file, a savefile, or the name of an external file. Cache files are specified in single quotes and external files are in double quotes. If the path to the destination file does not already exist, it will be created.

If the source and target are paths ending in "/", the contents of the source directory (including sub-directories) will be copied to the target path.

This instruction could be useful when players upload files (like code) that you might want to dump to an external file.

Example:

mob/verb/change_world(F as file) fcopy(F,"world.dm") shell("DreamMaker world") world.Reboot()

This (somewhat dangerous) example allows players to upload code, recompile, and reboot the world. It assumes that DreamMaker is in the path where the shell looks for executable files and also that the name of the running world is world.dmb.


fcopy_rsc proc

See also:
cache
fcopy proc
file proc
load_resource proc
Format:
fcopy_rsc(File)
Args:
File: file to copy into the resource cache
Returns:
reference to the file as a cache entry

The file to copy may either be a file name (text string) or the return value of file() operating on the same. If a cache entry is passed as the argument, it will simply be returned with no action necessary.

Once a file has been copied into the resource cache (i.e. the world's .rsc file), it may be used as an icon or a sound or whatever is appropriate. Most internal operations involving resource files automatically perform this operation when you try to use an external file in place of a cache entry. For example, when assigning a file() object to atom.icon, fcopy_rsc() is implicitly invoked.

The main reason you would ever want to call this explicitly is if you are storing references to resource files in your own data structures and you want to ensure that all values are converted to cache entries so they may be directly compared to one another.


fdel proc

See also:
shell proc
Format:
fdel(File)
Args:
File: name of file to delete
Returns:
1 on success; 0 otherwise.

If the specified file ends in '/', it is treated as a directory. Any contents (including sub-directories) are deleted as well.

Be careful!


fexists proc

See also:
flist proc
ftime proc
length proc
Format:
fexists(File)
Args:
File: name of file to test
Returns:
1 if file exists; 0 otherwise.

file proc

See also:
<< output operator
fcopy_rsc proc
ftp proc
isfile proc
link proc
run proc
savefile
sound proc
Format:
file(Path)

Returns a file object corresponding to the named file. This file object can then be used in a variety of ways. One would be to send it to a player to view using the browse() instruction. Output may also be appended to the file using the << operator.

Note that the file exists in the external filesystem (ie the hard disk) and not the cache. That means the path is specified in double quotes and will be evaluated at run-time rather than compile-time. The file need not exist at compile time and may even be modified at a later date. This is the principle reason for using a file in the filesystem rather than a cached resource file (specified in single quotes).

Example:

mob/verb/help() usr << browse(file("help.html"))

Many DM instructions that deal with files treat file("name") and "name" the same. There are cases such as browse() where a simple text string is not interpreted as a filename; it is in those situations where file() is really necessary.


file2text proc

See also:
shell proc
text2file proc
Format:
file2text(File)
Args:
File: file to read
Returns:
the contents of the file.

This can be useful when interacting with external applications that generate output in a text file. For example, you might have an external program that mimics conversation:

Example:

mob/oracle/verb/tell(T as text) text2file(T,"talk.in") shell("talk < talk.in > talk.out") usr << file2text("talk.out")

filter proc

See also:
filters var (atom)
Filter effects
Format:
filter(type = Type, parameter = Value, ...)

Creates a graphical filter that can be assigned or added to a list of filters on an atom or image.

This proc uses named arguments, and the "type" value must always be included. To see which types of filters are available and what parameters they accept, see Filter effects.

Example:

atom/proc/Highlight(apply) if(apply) filters = filter(type="outline", size=1, color=rgb(255,0,0)) else filters = null

A filter created with this proc is an abstract filter; it is not associated with any atom. When you add it to atom's filters, the atom gets a copy of this filter, so changing the abstract filter's values afterward will not change the atom's filters. For the same reason, an abstract filter can't be animated.

A filter that is part of an atom's filters list, like obj.filters[1], is an attached filter. Changing the values for an attached filter will change how that atom is displayed, and attached filters can be animated.


findlasttext proc

See also:
findtext proc
findtextEx proc
findlasttextEx proc
Format:
findlasttext(Haystack,Needle,Start=0,End=1)
Returns:
The last position of Needle in Haystack; 0 if not found.
Args:
Haystack: The text string to search.
Needle: The sub-text to search for.
Start: The text byte position in Haystack in which to begin the search. Because this searches backwards, the default is the end of the string (0).
End: The earliest position in Haystack that can be matched as a result.

This instruction is NOT sensitive to the case of Haystack or Needle. The case-sensitive version is findlasttextEx().

If the start or end position is negative, the position is counted backwards from the end of the string. E.g., findlasttext("Banana", "na", -3) starts three characters from the end and will skip over the last "na".

Note: Unlike findtext(), a regular expression may NOT be used as the Needle. Searching backwards is simply too complex for the regular expression engine.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use findlasttext_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


findlasttextEx proc

See also:
findtext proc
findtextEx proc
findlasttext proc
Format:
findlasttextEx(Haystack,Needle,Start=0,End=1)
Returns:
The last position of Needle in Haystack; 0 if not found.
Args:
Haystack: The text string to search.
Needle: The sub-text to search for.
Start: The text byte position in Haystack in which to begin the search. Because this searches backwards, the default is the end of the string (0).
End: The earliest position in Haystack that can be matched as a result.

This instruction is sensitive to the case of Haystack and Needle. The case-insensitive version is findlasttext().

If the start or end position is negative, the position is counted backwards from the end of the string.

Note: Unlike findtextEx(), a regular expression may NOT be used as the Needle. Searching backwards is simply too complex for the regular expression engine.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use findlasttextEx_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


findtext proc

See also:
findlasttext proc
findtextEx proc
replacetext proc
Regular expressions
Format:
findtext(Haystack,Needle,Start=1,End=0)
Returns:
The first position of Needle in Haystack; 0 if not found.
Args:
Haystack: The text string to search.
Needle: The sub-text to search for. May be a regular expression (regex).
Start: The text byte position in Haystack in which to begin the search.
End: The text byte position in Haystack immediately following the last character to search.

When Needle is text, this instruction is NOT sensitive to the case of Haystack or Needle. The case-sensitive version is findtextEx().

Example:

if(findtext("Hi There","there")==0) world << "Not found!" else world << "Found!"

This outputs "Found!", since "there" is a part of the string "Hi There", ignoring case.

If the start or end position is negative, the position is counted backwards from the end of the string. E.g., findtext("Banana", "na", -3) starts three characters from the end and only searches the final "ana".

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use findtext_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


findtextEx proc

See also:
findtext proc
replacetextEx proc
Regular expressions
Format:
findtextEx(Haystack,Needle,Start=1,End=0)
Returns:
The position of Needle in Haystack; 0 if not found.
Args:
Haystack: The text string to search.
Needle: The sub-text to search for. May be a regular expression (regex).
Start: The text byte position in Haystack in which to begin the search.
End: The text byte position in Haystack immediately following the last character to search.

When Needle is text, this instruction is sensitive to the case of Haystack and Needle. The case-insensitive version is findtext().

Example:

if(findtextEx("Hi There","there")==0) world << "Not found!" else world << "Found!"

This outputs "Not found!", since "there" is not a part of the string "Hi There", taking into account case.

If the start or end position is negative, the position is counted backwards from the end of the string. E.g., findtextEx("Banana", "na", -3) starts three characters from the end and only searches the final "ana".

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use findtextEx_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.

Note: This proc used to be named findText, like findtext but with a capital T. To avoid confusion it has been renamed, but old code will still compile.


flick proc

See also:
icon_state var (atom)
Format:
flick(Icon,Object)
Args:
Icon: An icon file or state name.
Object: The target object.

Cause the icon attached to Object to be temporarily replaced with the specified icon or icon state for the duration of the animation. This is a purely visual effect and does not effect the actual value of the object's icon variable.

Example:

flick('blink.dmi',usr) //show another icon flick("fight",usr) //show usr's fight state

The target object may be any atom or image.


flist proc

See also:
fexists proc
Format:
flist(Path)
Args:
Path: The path in the filesystem to get a listing of.
Returns:
A list of files contained in the specified directory and whose names begin with the specified text. The names of sub-directories are listed too, and are marked by a trailing "/".

The path is of the form "dir1/dir2/.../file". Only files beginning with the "file" part are listed, so be sure to end a directory name with "/" if you wish to see its contents. Otherwise you will just get that directory name back with a "/" appended.

Only files and sub-directories directly contained in the specified path are listed (ie not the contents of the sub-directories too). The file names in the list do not include the path information but just the bare file name.


floor proc

See also:
ceil proc
round proc
trunc proc
fract proc
Format:
floor(A)
Returns:
the floor of A
Args:
A: A number.

Returns the floor of A (the largest integer less than or equal to A).

Example:

usr << floor(1.45) // outputs 1 usr << floor(-1.45) // outputs -2

for proc

See also:
for list proc
for loop proc

The for proc can be used to iterate values over a fixed range or list. Consult the appropriate entry for more information.


for list proc

See also:
for loop proc
list
istype
Format:
for (Var [as Type] [in List]) Statement
for (Var in Start to End [step Step]) Statement
Args:
Var: A variable to sequentially contain each member of the list.
List: The list to loop through. This defaults to the whole world.
Type: One or more of area, turf, mob, or obj, ORed together. If no type is specified, the declared type of Var will be used to skip over inappropriate elements in the list.
Start: A starting numeric value.
End: An ending numeric value (inclusive).
Step: An increment for the numeric value; default is 1.

Example:

usr << "Mobs:" var/mob/M for(M in view()) usr << M.name

This loops M through the mobs in view(), outputting the name at each iteration.

When you loop through a list, with the exception of looping through world, you're actually looping through a copy of that list. If the list changes, those changes won't have any bearing on this loop. If you want to be able to handle a list that might change, you'll need to use the for loop proc instead.

You can declare the variable right inside the for statement. Its scope is entirely contained within the for statement, so it will not conflict with a similar variable declared elsewhere in the same procedure.

Example:

client/verb/who() for(var/client/Player) usr << Player

If the loop var has a type, a hidden istype() call is included in the code. Only items of that type, or its descendants, are handled within the loop. That means null values and objects of unrelated types will be skipped.

The numeric loop form is a quick internal version of the for loop proc. It's equivalent to for(Var = Start, Var <= End, Var += Step) unless Step is negative, in which case a >= comparison is used instead. The main difference is that unlike in a for loop proc, the values of Step and End are calculated at the beginning and never change after that, so an expression like list.len that might be subject to change will not be read again—in much the same way that looping through a list only loops through a copy of that list.

Example:

for(var/count in 1 to 100) src << count

Note: Although you can use fractional values for step in this numeric format, there may be accuracy considerations to keep in mind. See Numbers for more information.


for loop proc

See also:
break statement
continue statement
do proc
for list proc
while proc
Format:
for(Init, Test, Inc) Statement

First execute Init. Then if Test is true (non-zero), execute Statement. After this execute Inc. Continue checking Test, doing Statement, and performing Inc until Test turns out to be false (zero).

Statement may be a code block or a single statement. Semicolons may be substituted for commas inside the parentheses as a convenience to C/C++ programmers.

Init and Inc may be omitted. If Test is omitted, the loop will continue forever (unless a break, goto, or return instruction is used to get out of the loop).

Example:

var/i for(i=0, i<3, i++) world << i

This outputs:

0 1 2

Note: An Inc statement like i += 0.1 is perfectly valid, but you should keep in mind that numerical accuracy is not exact. See Numbers for more information.


fract proc

See also:
trunc proc
floor proc
ceil proc
round proc
Format:
fract(A)
Returns:
fractional part of A
Args:
A: A number.

Returns the fractional part of the number A, with the same sign. This is everything after the decimal point.

Example:

usr << fract(1.45) // outputs 0.45 usr << fract(-1.45) // outputs -0.45

ftime proc

See also:
time2text proc
flist proc
fexists proc
length proc
Format:
ftime(File, IsCreationTime)
Args:
File: name of file to test
IsCreationTime (optional): true to return file creation time, false (default) to return last-modified time
Returns:
A time value that can be sent to time2text().

ftp proc

See also:
<< output operator
browse proc
file proc
link proc
run proc
sound proc
Format:
target << ftp(File, Name)

Sends a file to the target with the (optional) suggested name for saving to disk. The file may be a cache file (loaded at compile time) or an external file (accessed at run-time). Cache files are specified in single quotes, and external files are in double quotes.

This function could be used to distribute source code, supplementary documentation, or anything.

Example:

mob/verb/geticon(O in view()) usr << ftp(O:icon)

This example allows the user to download the icons from other objects in the game.


generator proc

See also:
Generators
Particle effects
color var (atom)
Color matrix
stddef.dm file
Format:
generator(type, A, B, rand)
Args:
type: The type of generator object, which determines what kind of results it produces
A: One extreme of the generator results
B: The other extreme
rand: Type of random distribution used

Creates a generator that can be used to produce a random value. This generator can be used in client-side particle effects, or it can be used in proc code. The types of values it can produce are numbers, 3D vectors (list of 3 numbers), or colors (a text string like "#rrggbb" or a color matrix).

Generator typeResult typeDescription
numnumA random number between A and B.
vectorvectorA random vector on a line between A and B.
boxvectorA random vector within a box whose corners are at A and B.
colorcolor (string) or color matrixResult type depends on whether A or B are matrices or not. The result is interpolated between A and B; components are not randomized separately.
circlevectorA random XY-only vector in a ring between radius A and B, centered at 0,0.
spherevectorA random vector in a spherical shell between radius A and B, centered at 0,0,0.
squarevectorA random XY-only vector between squares of sizes A and B. (The length of the square is between A*2 and B*2, centered at 0,0.)
cubevectorA random vector between cubes of sizes A and B. (The length of the cube is between A*2 and B*2, centered at 0,0,0.)

The optional rand argument determines the type of random distribution.

UNIFORM_RANDDefault. Random values are uniformly likely to be chosen.
NORMAL_RANDApproximates a Gaussian normal distribution, but on a finite interval. Values closest to the mean are more likely to be chosen, while the extremes are much less likely.
LINEAR_RANDThe probability of choosing a number is proportional to its absolute value.
SQUARE_RANDThe probability of choosing a number is proportional to its square.

The result of calling generator() is a datum of type /generator and you can get a random value from it by calling its Rand() proc.

Example:

var/generator/G = generator("num", -1, 1) // generates a random number between -1 and 1 world << G.Rand() // generate a number and output it to world

get_dir proc

See also:
dir var (atom)
Format:
get_dir(Loc1, Loc2)
Returns:
The direction from Loc1 to Loc2. Possible results are NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, and SOUTHWEST.
Args:
Loc1: An object on the map.
Loc2: An object on the map.

If the direction is not directly lying along one of the four primary cardinal directions, the result will become the nearest diagonal direction (eg. if Loc2 is mostly north but a little to the east of Loc1, the direction returned will be NORTHEAST).


get_dist proc

See also:
bounds_dist proc
Format:
get_dist(Loc1, Loc2)
Returns:
The distance between Loc1 and Loc2, in tiles. This is the number of full-tile movements (disregarding any obstacles and allowing diagonal moves including across Z levels) required to go from one to the other. You can think of it as the max of their x, y, and z distances.
Args:
Loc1: An object on the map.
Loc2: An object on the map.

For a distance in pixels, use bounds_dist().

get_dist() will return -1 when Loc1 and Loc2 are the same object. If one or both of them is not on the map, an infinite value is returned.

Note: Prior to BYOND 515, get_dist() never returned a value greater than 127, which it counted as "infinite".


get_step proc

See also:
step proc
walk proc
Format:
get_step(Ref, Dir)
Returns:
The location of the new position.
Args:
Ref: Starting point or object.
Dir: One of NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST.

Calculate the position of a step from Ref in the direction Dir.


get_step_away proc

See also:
step_away proc
walk_away proc
Format:
get_step_away(Ref, Trg, Max=5)
Returns:
The location of the new position, or 0 if no change.
Args:
Ref: Starting point or object.
Trg: An object on the map.
Max: The maximum distance between Ref and Targ before movement halts.

Calculate position of a step from Ref on a path away from Trg, taking obstacles into account. If Ref is farther than Max steps from Trg, 0 will be returned.


get_step_rand proc

See also:
step_rand proc
walk_rand proc
Format:
get_step_rand(Ref)
Returns:
The location of the new position, or 0 if no change.
Args:
Ref: Starting point or object.

Calculate position of a step from Ref in random motion.


get_step_to proc

See also:
step_to proc
walk_to proc
get_steps_to proc
Format:
get_step_to(Ref, Trg, Min=0)
Returns:
The location of the new position, or 0 if no change.
Args:
Ref: Starting point or object.
Trg: An object on the map.
Min: The minimum distance between Ref and Trg before movement halts.

Calculate the position of a step from Ref on a path to Trg, taking obstacles into account.

If Ref is within Min steps of Trg, no step is computed. This is also true if the target is too far away (more than twice world.view steps). In either case, null is returned.


get_step_towards proc

See also:
step_towards proc
walk_towards proc
Format:
get_step_towards(Ref, Trg)
Returns:
The location of the new position.
Args:
Ref: Starting point or object.
Trg: An object on the map.

Calculate the position of a step from Ref in the direction of Trg.


get_steps_to proc

See also:
step proc
step_to proc
walk_to proc
get_step_to proc
Format:
get_steps_to(Ref, Trg, Min=0)
Returns:
A list of directions to step.
Args:
Ref: Starting point or object.
Trg: An object on the map.
Min: The minimum distance between Ref and Trg before movement halts.

Calculate a set of steps from Ref on a path to Trg, taking obstacles into account. The result of the proc is a list of directions that can be used with step(), or null if a path could not be found.

If Ref is within Min steps of Trg, no steps are computed. This is also true if the target is too far away (more than twice world.view steps). In either case, null is returned.


goto proc

See also:
break statement
continue statement
do proc
for loop proc
for list proc
while proc
Format:
goto node

Jump to the specified node in the current proc.

Example:

goto End world << "ERR" End world << "The end"

This displays "The end".

Note: goto should be used judiciously. It's easy to fall into the trap of "spaghetti logic" where goto is relied on so much that it becomes too difficult to follow how the flow of code execution will proceed. Normally, you'll want to use a construct like while() or for() loops, and break and continue statements. goto is for more complex situations that aren't readily handled by any of these.


gradient proc

See also:
Color gradient
rgb proc
rgb2num proc
Color space
Format:
gradient(Item1, Item2, ..., index)
gradient(Gradient, index)
Args:
Gradient: A color gradient list
Item1, Item2...: Elements of a color gradient list
index: The index along the gradient where the interpolation is done.
Returns:
A color, represented by a text string in #RRGGBB or #RRGGBBAA format

Interpolates between two or more colors along a color gradient. By default, gradients extend from an index of 0 to 1, but they are allowed to go beyond that if you choose.

The simplest way to use this proc is to interpolate between two colors:

Example:

// 20% of the way from red to black // prints #cc0000 which is rgb(204,0,0) src << gradient("red", "black", 0.2)

Anything that applies to color gradients can be used in this proc, so you can have a looping gradient, or a gradient that uses a color space other than RGB.

In the first format where you specify all the items separately, you can use named arguments for index and space (the gradient's color space). If you don't specify an argument called "index", the last argument is assumed to be the index.

Example:

// This gradient loops through all the hues and goes from 0 to 6. // Because this is a looping gradient, index=10 becomes index=4. // In HSL, this will give you blue (#0000ff). src << gradient(0, "#f00", 3, "#0ff", 6, "#f00", "loop", space=COLORSPACE_HSL, index=10)

The gradient(Gradient, index) format is used for cases where you want to pass an existing gradient to the proc.

Example:

var/candy_cane_gradient = list(0.5,"red",0.5,"white","loop") // the color output alternates between red and white depending on the current time src << gradient(candy_cane_gradient, world.time/100)

hascall proc

See also:
call proc
Format:
hascall(Object,ProcName)
Args:
Object: source of proc or verb
ProcName: name of proc or verb ("MyProc")
Returns:
1 if object has such a proc or verb; 0 otherwise

hearers

See also:
ohearers
view proc
viewers
Format:
hearers(Depth=world.view,Center=usr)

This is just like viewers(), but it is a list of mobs that can hear the center object. Currently, this is computed on the assumption that opaque objects block sound, just like they block light.


html_decode proc

See also:
html_encode proc
Format:
html_decode(HtmlText)
Args:
HtmlText: text to be "unescaped"
Returns:
unescaped text

Special characters such as < and > are not displayed literally in html and may produce garbled output. To display these characters literally, they must be "escaped". For example, < is produced by the code &lt; and > is produced by the code &gt;.

The html_decode() instruction takes a text string containing such escaped symbols and turns them into their literal counterparts. The more useful function is html_encode() which does the reverse.


html_encode proc

See also:
html_decode proc
Format:
html_encode(PlainText)
Args:
PlainText: text to be html "escaped"
Returns:
escaped text

Special characters such as < and > are not displayed literally in html and may produce garbled output. If you want to ensure that an entire text string is displayed literally, you can "escape" those characters. For example, < is produced by the code &lt; and > is produced by the code &gt;.

The html_encode() instruction does this for you automatically. If you wanted to disallow html input from players, you could use this to force their text to be displayed literally:

Example:

mob/verb/say(T as text) view() << "[usr] says, '[html_encode(T)]'"

If a URL is included in the text, special characters like & that are part of the URL will be skipped. This keeps automatically created links in the output from being broken.

Note for BYOND oldies: the old-style formatting codes such as "\red" which are still parsed but not encouraged are completely stripped out by html_encode().


icon proc

See also:
file proc
icon_states proc
icons
Format:
icon(icon,state,dir,frame,moving)
(supports named arguments)
Args:
icon: an icon file or /icon object
icon_state: an optional text string, specifying a single icon state to load
dir: an optional direction to extract
frame: an optional animation frame to extract
moving: Non-zero to extract only movement states, 0 for non-movement states, or null (default) for both

This is equivalent to new/icon(). It creates an /icon object, which is initialized to contain the same graphical data as the given file. If an icon state or direction are specified, only those parts of the original icon will be included in the new icon object.


icon_states proc

See also:
icons
icon_size var (world)
map_format var (world)
Big icons
Tiled icons
Format:
icon_states(Icon, mode=0)
Returns:
A list of text strings.
Args:
Icon: the icon being accessed
mode: applies to icons larger than one tile when using map_format=TILED_ICON_MAP; see below

Icons may have one or more internal states, which are identified by name. The state "" is the default.

If you are not using the TILED_ICON_MAP value for world.map_format, you can ignore the mode argument.

When graphics bigger than world.icon_size are used as an icon, and the map_format in use is TILED_ICON_MAP, they are internally broken up into tiles, one per icon state. The mode argument was added for big icons that get split into several smaller tiles. Those icons have several smaller states per true icon_state. For example if your 64×64 icon has a state named "open", it will contain states "open", "open 0,0", "open 1,0", "open 0,1", and "open 1,1" which are all used internally. (If the state name is blank, the sub-states are just "0,0", etc.) When using the TILED_ICON_MAP format, you need these for displaying the icon over several different atoms.

mode=0 will only show the sub-states ("open 0,0" and so on), all of which can be safely extracted in a single-tile icon via the icon() proc. mode=1 will show the main state names ("open"); any time you work with that state name you're working with the full-size icon. mode=2 will show all of the states.


if proc

See also:
goto proc
Format:
if( E ) Statement1
else if( E2 ) Statement2
else Statement3

If the expression E is true (non-zero) then execute Statement1. Otherwise, test E2, etc. Finally, if none of the expressions are true, execute Statement3. The else nodes are all optional.

Statement1, Statement2, and Statement3 may be a single statement or a code block with optional braces: {}.

Example:

if(T==1) world << "TRUE" else world << "FALSE"

This will display "TRUE" if T has value 1, and "FALSE" otherwise.


image proc

See also:
<< operator
del proc
icon
image objects
images var (client)
overlays var (atom)
Format:
image(icon,loc,icon_state,layer,dir)
(supports named arguments)
Returns:
An image reference on success; 0 on failure.
Args:
icon: An icon, object prototype, object instance, or other image.
loc: The location at which to display the image.
icon_state: The icon state to use.
layer: The drawing layer to use.
dir: The direction to orient the image.

Images are "virtual" objects, which have a purely visual effect. Once created, they can be made to appear to selected players. The image() instruction is simply a short-hand for new/image().

The image remains attached to the location specified by loc. For example, if loc is a mob, the image will appear above the mob until it is destroyed.

The arguments icon_state, layer, and dir may be used to override the settings associated with the icon or object used to create the image. For example, the default drawing layer for an plain icon is FLY_LAYER (above all other objects), but you could change this to OBJ_LAYER to make it appear under mobs on the map.

Example:

var/Box Box = image ('highlight.dmi', usr) usr << Box ... del(Box) //when done, remove image

Another common use of images is in making an overlay:

overlays += image('pants.dmi',icon_state = "red")

Since the loc argument could never be a text string, the above statement can be further shortened:

overlays += image('pants.dmi',"red")

This is much preferable to achieving the same effect with icon('pants.dmi',"red"), since that involves the overhead of creating a new icon file, which should only be done when it is really necessary.


initial proc

See also:
:: operator
issaved proc
vars list var (datum)
Format:
initial(Var)
Args:
Var: A variable to find the initial value of.

This returns the original compile-time value of a variable. It could be used to reset a variable to its default value or to check if a variable has changed.

Example:

obj/verb/set_icon(I as null|icon) if(!I) I = initial(icon) icon = I This example allows an object's icon to be modified. If the user does not specify a new icon, it will be reset to the original one.

input proc

See also:
alert proc
arguments (verb)
Format:
input(Recipient=usr,Message,Title,Default) as Type in List
Returns:
User's response.
Args:
Recipient: The user who will see this input prompt.
Message: A message in the prompt, to tell the user what it's asking for.
Title: The title of the prompt window.
Default: Default value if the user cancels the input.
Type: A verb input type, such as text, message, num, anything. If you omit "as Type", the type defaults to text.
List: An optional list of items to choose from.

Creates a prompt dialog that asks the user for a response. The current proc sleeps until they respond.

The only required argument is the message. The type may be any combination of input types allowed for verb arguments, which can be combined with the | operator. The null type will allow the user to cancel, e.g. as null | anything in contents.

Example:

mob/verb/create_character() usr.name = input("Choose a name for your character.", "Your Name", usr.name) usr.gender = input("Select a gender for your character.", "Your Gender", usr.gender) in list("male","female","neuter")

If the target of the input prompt is not a player, the result will be the default value. If no default value is specified and null is allowed by the input type, null will be returned. Otherwise, an error will result, crashing the proc that called input().

A more common use for input() is to give a player a list of things to choose from. For example, this is a simple shopkeeper NPC, where the shopkeeper's inventory is its contents.

Example:

mob/shopkeeper/verb/Buy() var/list/options = list() var/obj/item for(item in src) // show a pretty list of options with prices included options["[item]: $[item.price]"] = item var/choice = input("Buy something!", "Shop") as null|anything in options item = options[choice] if(!item) return // user canceled if(item.price > usr.gold) usr << "You can't afford that." else // give the buyer a copy of the item var/t = item.type new t(usr) usr.gold -= item.price usr << "You bought \a [item] for $[item.price]."

Using as num is another popular input choice, which you might use for haggling, deciding how many of an item to pick up or drop, etc.

This next part is important! Always validate input from a user to make sure it's correct.

You should be sure to sanitize any user input to make sure the value is valid. For instance, if you have a verb that gives gold to another player, you should check that the amount isn't negative and doesn't contain any fractions, and isn't more than they have.

Example:

mob/player/verb/Give_Gold() set src in oview(1) var/amount = input("How much?", "Give gold") as null|num if(isnull(amount)) return amount = floor(amount) // round down to a whole number amount = min(amount, usr.gold) // don't give more than you have if(amount <= 0) return // ignore negatives and 0 gold += amount usr.gold -= amount usr << "You gave [src] $[amount]." src << "[src] gave you $[amount]."

Likewise if you're allowing a user to input text, it too should be sanitized. If they shouldn't enter multi-line text, you should strip out "\n" characters. If they're putting in something like a character name, strip out any HTML via html_encode(), or you can simply reject anything that contains invalid characters and make them do it again.


isarea proc

See also:
isloc proc
Format:
isarea(Loc1, Loc2 ...)
Args:
Any number of locations to test.
Returns:
1 if all args are valid areas; 0 otherwise

isfile proc

See also:
cache
file proc
isicon proc
Format:
isfile(File)
Args:
File: the value to test

This returns a true value when given a file. Both objects returned by file() and files stored in the resource cache qualify.


isicon proc

See also:
cache
icon
isfile proc
Format:
isicon(Icon)
Args:
Icon: the value to test
Returns:
1 if the value is a valid icon; 0 otherwise.

This returns a true value when given an icon. Both /icon memory objects and icon files stored in the resource cache qualify.


isinf proc

See also:
isnum proc
isnan proc
Numbers
Format:
isinf(n)
Args:
n: A number
Returns:
1 if this is an infinite numeric value, either positive or negative; 0 otherwise

islist proc

See also:
list
list proc
Format:
islist(Object)
Args:
Object: The value to test
Returns:
1 if the object is a valid list; 0 otherwise.

Tests whether an object is a list. This includes user-defined lists, special lists like contents and overlays, and more.


isloc proc

Format:
isloc(Loc1, Loc2 ...)
Args:
Any number of locations to test.
Returns:
1 if all args are valid locs; 0 otherwise.

Tests validity of a location. If all arguments are mobs, objs, turfs, or areas, this returns 1.

For a single argument this is equivalent to: (ismob(Loc) || isobj(Loc) || isturf(Loc) || isarea(Loc)).


ismob proc

See also:
isloc proc
ismovable proc
Format:
ismob(Loc1, Loc2 ...)
Args:
Any number of locations to test.
Returns:
1 if all args are valid mobs; 0 otherwise

ismovable proc

See also:
isloc proc
isobj proc
ismob proc
Format:
ismovable(Loc1, Loc2 ...)
Args:
Any number of locations to test.
Returns:
1 if all args are valid objs or mobs; 0 otherwise

Movable atoms are either objs or mobs, so this combines the isobj and ismob tests into a single proc.


isnan proc

See also:
isnum proc
isinf proc
Numbers
Format:
isnan(n)
Args:
n: A number
Returns:
1 if this is a numeric value but is an invalid "not a number" (NaN); 0 otherwise

Some math operations return the special number NaN if they're undefined, such as dividing 0 by 0. This tells you if a number is that type.

NaN is never greater than, less than, or equal to another number, even itself.


isnull proc

See also:
null
Format:
isnull(Val)
Returns:
1 if Val is null; 0 otherwise

isnum proc

See also:
isinf proc
isnan proc
Numbers
Format:
isnum(Val)
Returns:
1 if Val is a number; 0 otherwise

isobj proc

See also:
isloc proc
ismovable proc
Format:
isobj(Loc1, Loc2 ...)
Args:
Any number of locations to test.
Returns:
1 if all args are valid objs; 0 otherwise

ispath proc

See also:
typesof proc
Format:
ispath(Val)
ispath(Val,Type)
Returns:
single-argument: 1 if Val is a type path
double-argument: 1 if Val is a type path derived from Type; 0 otherwise.
Args:
Val: A type path.
Type: A type path or instance.

Example:

var/M M = /mob/ugly/duckling if(ispath(M,/mob/ugly)) //true if(ispath(M)) //true if(ispath(new/mob)) //false

ispointer proc

See also:
* operator (pointers)
& operator (pointers)
Format:
ispointer(Value)
Args:
Value: The value to test
Returns:
1 if the value is a pointer; 0 otherwise.

Tests whether an value is a pointer.

Note: This does not check if the pointer is still valid, like for instance if the object it belongs to has been deleted, or if it points to a list index that is now out of bounds.


issaved proc

See also:
initial proc
savefile
tmp vars
vars list var (datum)
Format:
issaved(Var)
Args:
Var: The variable to test.

This returns 1 if the given variable should be automatically saved when writing an object to a savefile and 0 otherwise. Variables which are not global, const, or tmp will return 1.


istext proc

Format:
istext(Val)
Returns:
1 if Val is text; 0 otherwise

isturf proc

See also:
isloc proc
Format:
isturf(Loc1, Loc2 ...)
Args:
Any number of locations to test.
Returns:
1 if all args are valid turfs; 0 otherwise

istype proc

See also:
ispath proc
locate proc
typesof proc
__IMPLIED_TYPE__ macro
Format:
istype(Val,Type)
istype(Val)
Returns:
1 if Val is derived from Type; 0 otherwise.
Args:
Val: An object instance.
Type: An object prototype or instance. If no type is specified and a variable was passed in as the first argument, it will default to the declared type of the variable.

If you don't have an object instance to test, but just want to see if one prototype derives from another one, use ispath() instead.

Example:

var/M M = new/mob/ugly/duckling() if(istype(M,/mob/ugly)) //this will be true usr << "[M] is ugly!"

Using implicit types, that same example can be rewritten as follows:

var/mob/ugly/M M = new/mob/ugly/duckling() if(istype(M)) //this will be true usr << "[M] is ugly!"

jointext proc

See also:
splittext proc
Join proc (list)
Format:
jointext(List,Glue,Start=1,End=0)
Returns:
A text string made up of the items in List, joined together by Glue.
Args:
List: The list to be joined.
Glue: The text that will go between each item.
Start: The list item on which to begin.
End: The list item immediately following the last item to be joined.
include_delimiters: True if any delimiters found should be included in the result.

Any items in List that are not already text will be converted to text. The Glue string only goes between two items, so a single-item list is the same as converting that one item to text, and an empty list becomes an empty string.

Example:

var/list/items = list("apples", "oranges", "bananas") usr << jointext(items, ", ")

If the start or end position is negative, the position is counted backwards from the end of the list.

Calling List.Join(Glue,Start,End) is the same thing, as long as List is a valid list.


json_decode proc

See also:
json_encode proc
Format:
json_decode(JSON)
json_decode(JSON, flags)
Returns:
A value interpreted from a JSON-formatted text string.
Args:
JSON: The JSON-formatted text to decode.
flags: A set of flags that tell the decoder how to act.

Arrays like [1,2,3] will be converted to regular lists like list(1,2,3).

Object literals like {"a":1} will be converted to associative lists such as list("a"=1). Each item in the list is also decoded. Except in strict mode, non-string values are allowed as the "keys" in an associaitve list, even though that's not valid JSON, and strings used as keys can be left unquoted. BYOND doesn't care, as long as it can understand the formatted text it's given. The only exception is that a number isn't allowed to be an associative list key, and will be converted to a string instead, so {1:2} becomes list("1"=2).

Special numbers NaN and Infinity are recognized correctly (these are case-sensitive). All other numbers are parsed and stored in the regular BYOND format (32-bit floating point).

Since BYOND doesn't have dedicated boolean values, true and false are interpreted as 1 and 0, respectively.

The JSON_STRICT flag uses stricter JSON parsing rules and will not allow some things. In strict mode:

The JSON_ALLOW_COMMENTS flag allows you to include // single-line comments and /* ... */ long-form comments in the text to be decoded. This can be mixed with the strict flag. This flag is now used by default.


json_encode proc

See also:
json_decode proc
Format:
json_encode(Value)
json_encode(Value, flags)
Returns:
A JSON-formatted text string representing Value.
Args:
Value: The value to encode.
flags: A set of flags that tell the encoder how to act.

If Value is a simple list or a matrix, the result will be formatted as a JSON array, and each item in the list is encoded.

If Value is an associative list, the result will be formatted as a JSON object literal, and each item and associated value is encoded. (The keys in the object literal don't have to be strings. Even though that isn't valid JSON, BYOND doesn't care. Be aware however that strict JSON parsers will care.)

Datums are not serialized, but are converted to the equivalent of "[Value]" instead.

The special numbers NaN and infinity will be encoded as object literals in a form like {"__number__":"NaN"}.

Example:

var/list/info = list("name"="fridge", "power"=12) // send {"name":"fridge","power":12} to a JavaScript function usr << output(url_encode(json_encode(info)), "mybrowser:myJSfunction")

BYOND formatting such as \red is removed from encoded strings.

Situations where a list has a reference to itself will cause the nested version to print a null value instead.

The JSON_PRETTY_PRINT flag introduces spacing into the output for improved readibility. Spaces will be added after colons and commas. Non-empty arrays and object literals will have a line break and tabs before each item, and a line break with one fewer tab before the closing bracket or brace. (The special formatting for numbers like Infinity, or the list form for matrices, will not be given tabs and line breaks.)


length proc

Format:
length(E)
Returns:
The length of the data associated with E.
Args:
E: a text, list, or file

Example:

world << length("Hi")

This outputs, "2", the length of the string "Hi".

Example:

world << length(list(1,2,3))

This outputs, "3", the length of the list.

Example:

world << length(file("test.txt"))

This outputs the length of the file.

Note: In strings containing non-ASCII characters, this is the length in bytes, not characters; a character may span multiple bytes. Use length_char() to work with character counts instead of bytes. See the Unicode section for more information.


lentext proc

See also:
length proc
Format:
lentext(T)
Returns:
The length of text T.
Args:
T: A text string.

Deprecated. Use length() instead.


link proc

See also:
<< output operator
Topic proc (client)
file proc
run proc
Format:
O << link(url)

This causes the recipient (O) to view the specified url. The url could be a web or BYOND address. In the latter case, the player will disconnect from the current world and connect to the specified one.

The format of a BYOND url is as follows:

byond://address:port?TopicData

To access a registered world, address:port may be replaced by the registered name in the hub. The optional topic data is processed by the world once the player has connected. If only a topic is specified, the current world processes it.

Example:

usr << link("byond://byond.com:6000") //BYOND address usr << link("http://www.byond.com") //web address usr << link("?myTopic") //topic

list proc

See also:
arglist proc
list
list associations
Format:
list(A,B,C,...)
or
list(A=a,B=b,C=c,...)
Returns:
A new list with contents A, B, C, and (optional) associated values a, b, c.
Args:
Arbitrary number of elements to be inserted into the list.

Assign elements to a list.

Example:

var/L[] L = list(1,2,3)

This creates a new list 'L' that initially contains elements 1, 2, and 3. The length of L is 3.

The list() instruction may also be used to create associative lists.

Example:

var/list/lst = list("player" = "James Byond", "score" = 2000)

That creates a list with contents ("player, "score") and associated values ("James Byond", 2000) respectively.

The index values should be constants, and that usually means text constants. When these index values happen to be text strings that satisfy all the requirements for variable names, this may also be written in a convenient short-hand without the double quotes:

var/list/lst = list(player = "James Byond", score = 2000)

In other words, this is exactly the same syntax as for named arguments.


list2params proc

See also:
Topic proc (client)
list associations
params var (world)
params2list proc
text2num proc
Format:
list2params(List)
Args:
List: List to encode as a text string.

This instruction converts a list of parameter names and associated values into a single text string suitable for use in a URL or similar situation. The format of the resulting text string is:

"name1=value1&name2=value2&..."

Special characters such as '=' and '&' inside the parameter names or values are written in the form: %xx where xx are two hexadecimal digits representing the ASCII value of the character. For Unicode characters, their UTF-8 encoding will be processed this way, which may make up multiple %xx sequences. In addition, spaces are converted to +.

This parameter format is the same one used by most HTML forms and is known by the MIME type application/x-www-form-urlencoded. It is often used in DM to pack information into topic links.

The original list has items "name1", "name2", and so on. These in turn are associated with the corresponding values "value1", "value2", and so on.

Example:

var/plist[0] plist["offense"] = "jwalk" plist["time"] = "10:00" usr << list2params(plist)

The above example creates a simple parameter list which associates the item "offense" with the value "jwalk" and the item "time" with the value "10:00". This will produce the text string "offense=jwalk&time=10:00".

Object values in the list (like say a mob) get turned into references in the parameter text, just as though you had embedded them with "\ref[Object]". When read back in with params2list(), you could convert these values back into real references by using locate().


load_resource proc

See also:
<< output operator
Format:
Player << load_resource(File)
Player << load_resource(File, KeepTime)
Player << load_resource(File1, File2..., KeepTime1, File3, File4..., KeepTime2...)
Args:
Player: A mob or client, a list of them, or world
File: A resource file (image or sound)
KeepTime: Minimum time (in seconds) to keep the file loaded; 0=default, -1=forever

Tells the player's client (or multiple players) to load the specified resources now, and how long to keep them. If you do not specify a keep time, 0 is used which will use the default time.

This may be useful for loading sounds into memory before they play, or to load an icon as soon as possible even if it hasn't been displayed yet. This can avoid delays later on when the resources are needed.

Dream Seeker keeps most assets loaded for at least 5 minutes (300 seconds) after their last use. However if you think a more appropriate time is closer to half an hour, you can set a keep time of 1800 seconds. Or if you want them to stay loaded indefinitely, set a keep time of -1.

Example:

mob/Login() ..() // load up these songs now and keep them loaded indefinitely src << load_resource('music1.ogg', 'music2.ogg', 'music3.ogg', -1)

In cases of extreme memory duress, Dream Seeker's garbage collector will get more aggressive and can still override your choices if need be.


locate proc

See also:
istype proc
tag var (datum)
__IMPLIED_TYPE__ macro
Format:
locate(Type) in Container
locate(X,Y,Z)
locate(Tag)
locate(TextRef)
Returns:
An object of the specified type or the turf at the given coordinates. If a text string is given in place of an object type, the object with the same tag is found. If a container is given, only objects directly within that object are searched.
Args:
Type: An object prototype or tag. If locate() is being used in an assignment to a variable with a declared type, this argument is optional and will default to the type of the variable being assigned.
Container: An optional container object. (The default is world.)
X,Y,Z: A set of numerical coordinates.
Tag: The value of an object's tag variable (must be unique).
TextRef: An embedded object reference created by the \ref text macro.

Types are matched in the same manner as istype(). In other words, locate(/obj) could return an instance of something derived from /obj, such as /obj/armor.

If there is more than one instance of the specified type, the first one found will be chosen.

Example:

var/mob/shopkeeper/M = locate() if(M) usr << "Found the shopkeeper." else usr << "Could not find the shopkeeper."

This looks for a mob of a type /mob/shopkeeper in the world (world.contents).

Example:

usr.Move(locate(/turf/Home))

This "teleports" the usr to a turf of the type /turf/Home.

Example:

usr.Move(locate(1,2,3))

This moves the usr to the turf at coordinates (x,y,z) = (1,2,3).


log proc

See also:
** operator
Format:
log(X,Y)
log(Y)
Returns:
The logarithm (base X) of Y. If X is not specified, a natural logarithm is computed (base 2.718...).

The logarithm is the power to which you have to raise X in order to get Y. In other words, the following is true (ignoring round-off error):

X ** log(X,Y) == Y

One nice property of this function is that it gradually increases, with a slope that continuously tapers off. In other words, it can be useful to represent diminishing returns from some input, such as money, experience points, and so forth.


lowertext proc

See also:
uppertext proc
Format:
lowertext(T)
Returns:
A lowercase text string.
Args:
T: A text string.

Make all of the characters of T lowercase.

Example:

L = lowertext("HI THERE") // = "hi there"

matrix proc

See also:
matrix
transform var (atom)
Format:
matrix()
matrix(Matrix)
matrix(a, b, c, d, e, f)
matrix(x, y, MATRIX_SCALE)
matrix(n, MATRIX_SCALE)
matrix(angle, MATRIX_ROTATE)
matrix(x, y, MATRIX_TRANSLATE)
Returns:
A new matrix.
Args:
Matrix: a matrix to copy
a - f: The individual matrix components (in column-major order)
x, y: Arguments affecting how the shortcut matrix format affects x and y
n: The same value used for x and y together
angle: Rotation angle in degrees, clockwise

If no arguments are provided, a new default (identity) matrix is created.

There are also several "shortcut" matrix calls that can be made:

matrix(x, y, MATRIX_SCALE)
matrix(n, MATRIX_SCALE)
A scaling matrix, scaling either x and y independently or both together
matrix(angle, MATRIX_ROTATE)
A matrix that rotates by the angle in degrees, clockwise
matrix(x, y, MATRIX_TRANSLATE)
A matrix that translates by x and y

max proc

See also:
min proc
clamp proc
Format:
max(A,B,C,...)
Returns:
the maximum of the arguments.

Example:

usr << max(1,2,3)

This example displays 3.

If a single argument is specified, this is expected to be a list and the maximum item from the list is returned. Items to be compared may be numbers, text strings, or null, but numbers and text strings may not be mixed.


md5 proc

See also:
sha1 proc
file proc
Format:
md5(T)
md5(F)
Returns:
text or null.
Args:
T: A text string.
F: A file.

This proc implements MD5 hashing. A hash function is a one-way process that compacts information to a short value: a hash. The same value will always have the same hash. Among other uses, most computers use hashing to store passwords. By storing just the hash, the password file contains very little sensitive information, but the password can still be verified by confirming that md5(password)==hash. MD5 is a widely-used hash function.

Example:

mob/var/hash mob/Read(savefile/S) ..() // hash was saved in the file along with other values if(md5("[level]/[exp]/[exp_needed]") != hash) src << "Cheater!" del(src)

In the example, a few vars belonging to a mob were saved along with a hash of those values. When the mob is loaded again, the game compares the hash to the values to make sure it's still accurate. If the values or hash had been changed by a sneaky player, they wouldn't match. (But a sneaky player could still calculate hash themselves if they knew the exact text used to make it, so this should be kept secret.)

If the argument is a file, md5() will read the file and return the MD5 hash of the file's entire contents. If the file doesn't exist, it returns null. The file may be a cache file or an external file.

Examples:

var/hash = "(insert hash value here)" // Compute this ahead of time // Check that the cached default icon is still the same if (md5('default.dmi') != hash) world << "The default icon has been modified!" // Or check that the entire game resource file is pristine if (md5(file("mygame.rsc")) != hash) world << "The game resources have been modified!"

Note that you must pass the result of file() in order to compute the hash of an external file's contents at runtime. Otherwise md5() will treat the filename as text and return the hash of the name only.

If T is anything but a text string or file, the proc returns null.


min proc

See also:
max proc
clamp proc
Format:
min(A,B,C,...)
Returns:
the minimum of the arguments.

Example:

usr << min(1,2,3)

This example displays 1.

If a single argument is specified, this is expected to be a list and the minimum item from the list is returned. Items to be compared may be numbers, text strings, or null, but numbers and text strings may not be mixed.


missile proc

Format:
missile(Type, Start, End)
Args:
Type: An object prototype or icon file.
Start: The starting location.
End: The ending location.

Send a missile of the given Type between two locations. The effect is purely visual. When Type is an object, its icon is used for the missile.

Example:

missile(/obj/fireball, usr, loc)

nameof proc

See also:
:: operator
Format:
nameof(Var)
nameof(ProcRef)
nameof(Path)
Args:
Var: A variable, e.g. src.density or foo::bar.
ProcRef: A proc reference, e.g. /mob::Enter().
Path: A type path, e.g. /obj/item/barrel.

This returns the name of a var or proc, or the last part of a type path. This proc only exists at compile-time.

The main purpose of this proc is to turn a proc reference into a name, which is useful in some esoteric situations.

Example:

var/list/event_queue proc/CallLater(object, procref, a, b, c) var/list/forlater = list(object, nameof(procref), a, b, c) event_queue ||= list() event_queue[++event_queue.len] = forlater world/Tick() while(length(event_queue)) var/list/forlater = event_queue[1] event_queue.Cut(1,2) var/object = forlater[1] var/procname = forlater[2] var/a = forlater[3] var/b = forlater[4] var/c = forlater[5] call(object, procname)(a, b, c)

new proc

See also:
New proc (atom)
New proc (datum)
New proc (icon)
newlist proc
path operators
__IMPLIED_TYPE__ macro
Format:
new Type(Args)
Returns:
A reference to a new instance of Type.
Args:
Type: The type of object to create.
Args: Arguments for the Type.New() proc.

A new instance of Type is created. The arguments (Args) are passed to its New() proc. A handy short-cut: if Type is not specified and new() is being used in an assignment, the variable type of the left-hand-side will be used as the default type.

The atom types /area, /turf, /obj, and /mob all take a location argument specifying the initial position. If not specified, it defaults to null.

Newly created areas or turfs replace any existing area or turf at the specified location.

Example:

obj/stick mob/verb/magic_stick() var/obj/stick/S = new(src) //create a stick in my inventory S.desc = "This is no ordinary stick!" view() << "[src] creates \an [S] from thin air!"

newlist proc

See also:
list proc
new proc
Format:
newlist(A,B,C,...)
Returns:
A list of new objects, just as though you had done list(new A,new B,new C,...).
Args:
Arbitrary number of types to be created in the list.

Example:

mob/contents = newlist(/obj/scroll/readme)

This causes new mobs to be created with a readme scroll in their inventory.

It is possible to make simple initializations when you want variables to have values other than the default for the particular type you are creating.

Example:

mob/contents = newlist( /obj/scroll/readme { name = "Introduction" desc = "The fate of Bracolia depends on you ..." } )

This is the most common use of "modified types", but it is not specific to the newlist instruction. Anywhere a type value may be used in DM, it may be followed by a list of initializations. The general syntax for a modified types is:

path {var1 = val1; var2 = val2}

The semicolon is necessary if you put several variable assignments on the same line. The braces are necessary, even though they are generally optional in DM (since the compiler looks at your indentation). The reason is that the path + initializations must be parsed as a single expression, which is a different context from the usual use of braces in DM when you are defining a true type. Also, indentation inside of an argument list is always ignored anyway.


noise_hash proc

See also:
rand proc
rand_seed proc
Format:
noise_hash(num1, num2, num3...)
noise_hash(list_of_nums)
noise_hash(hash_name, num1, num2, num3...)
noise_hash(hash_name, list_of_nums)
Returns:
A number between 0 and 1 (excluding 1 itself)
Args:
num1, num2, num3...: Numbers to be hashed (at least one)
list_of_nums: A list containing the numbers to hash
hash_name: A text string indicating the hash type (reserved for future use)

For some games using concepts of procedural generation, it's nice to be able to reliably create pseudo-random numbers in a repeatable, reliable way. This proc takes all the numbers put into it and hashes them together to get a value from 0 to 1. That output value will be the same for any given set of input numbers. This can be used on its own or as part of a more in-depth noise algorithm.

If the first argument is a string, that may be used in future versions to specify the type of hash to use. For now it is not used.

Non-numbers provided to the proc will be interpreted arbitrarily. Don't do that.


nonspantext proc

See also:
findtext proc
spantext proc
splittext proc
Format:
nonspantext(Haystack,Needles,Start=1)
Returns:
The number of consecutive characters, from the start position, that do NOT match the characters in Needles.
Args:
Haystack: The text string to search.
Needles: A text string with all the characters that should not match.
Start: The text byte position in Haystack in which to begin the search.

This proc is case-sensitive. A common use for this proc is in parsing. For instance nonspantext("apples, oranges",", ") will return 6, because the first 6 characters don't match a comma or a space.

If the start position is negative, the position is counted backwards from the end of the string.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use nonspantext_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


num2text proc

See also:
isnum proc
text2num proc
Format:
num2text(N, SigFig=6)
num2text(N, Digits, Radix)
Returns:
A text string.
Args:
N: A number.
SigFig: Number of significant digits.
Digits: Minimum number of digits
Radix: The base of the number, e.g. 16 is hexadecimal.

Get the text string for a number. The number of significant digits determines when scientific notation is used. The default is 6, so scientific notation will only be used when there are more than 6 digits.

Example:

T = num2text(12) // = "12" T = num2text(12,1) // = "1.2e1"

The Radix format is intended for converting numbers to bases other than 10, although you can still use 10. In this format, Digits represents the minimum number of digits to use, and the result will be left-padded with zeroes if necessary. Also, in this form only the integer part of the number is used, and it can't be any larger than what a 32-bit integer could store (about 4 billion). These limitations may be lessened or removed in the future, but this format was mainly intended for simple conversions.

Example:

world << num2text(11, 2, 16) // "0b" world << num2text(343, 0, 7) // "1000"

obounds proc

See also:
bounds proc
Format:
obounds(Ref=src, Dist=0)
obounds(Ref, x_offset, y_offset, extra_width=0, extra_height=0)
Returns:
A list of atoms within the given bounding box, excluding Ref.
Args:
Ref: A turf, obj, or mob.
Dist: A number (distance in pixels).
x_offset, y_offset: Shift to bounding box position (from Ref's bounding box)
extra_width, extra_height: Adjustment to bounding box size (from Ref's bounding box)

The results from obounds() are identical to bounds(), but obounds() leaves Ref out of the results.


ohearers

See also:
hearers
oview proc
oviewers
Format:
ohearers(Depth=world.view,Center=usr)

This is just like hearers(), but it excludes the center object and its contents from the list. It is a list of all other mobs that can hear the center object.


orange proc

See also:
<< output operator
block
oview proc
range proc
Format:
orange(Dist,Center=usr)
Returns:
A list of objects within Dist tiles of Center, excluding Center.
Args:
Dist: A number.
Center: An object on the map.

This instruction is identical to oview() except visibility is ignored. All objects are included in the list whether they are visible or not. The center object and its contents are excluded.


output proc

See also:
<< output operator
winclone proc
winset proc
Format:
output(msg, control)
Args:
msg: Text, an atom, a file, or null
control: The ID of a control in the player's skin, or null for the default

This is used in conjunction with the << output operator to send output to a particular control in the player's skin. If null is sent, the control will be cleared.

Example:

usr << output("Your score is [score].", "scorepane.output")

As with winset(), the control name may be in the form ":[type]" which sends to the default control of that type, e.g. ":output".

The control ID can be followed by a colon and extra info such as a name or a grid cell, which can send the output to the control in a different way. In a grid, this can output directly to a specific grid cell, like so:

Example:

usr << output("Column 3, Row 2", "examplegrid:3,2")

For a browser control, the extra info is a JavaScript function. The format for sending a script to the browser control is output("[params]","[control]:[scriptname]") where "[params]" is a URL-encoded list of string arguments to the javascript function, as formatted by list2params().

Example:

mob/Login() . = ..() usr << output(\ {" <script type="text/javascript"> function replace(v) { document.getElementById('foo').innerHTML = v.replace(/&/g, '&amp;').replace(/</g, '&lt;'); } </script> <div id="foo">This text can change.</div> <p>And this can't.</p> "}, ":browser"); #define LP(str) list2params(list(str)) mob/verb/newtext(T as text) usr << output(LP(T), ":browser:replace")

This allows for the creation of more dynamic interfaces, since javascript provides access to many client-side operations and flicker-free updates.


oview proc

See also:
<< output operator
orange proc
view proc
Format:
oview(Dist,Center=usr)
Returns:
A list of visible objects within Dist tiles of Center, excluding Center.
Args:
Dist: A number.
Center: An object on the map.

This instruction is just like view() except it doesn't include Center or its contents in the list.

Example:

oview() << "to others in sight of [usr]"

oviewers

See also:
hearers
oview proc
oviewers
Format:
oviewers(Depth=world.view,Center=usr)

This is just like viewers(), but it excludes the center object and its contents from the list. It is a list of all other mobs that can see the center object.


params2list proc

See also:
Topic proc (client)
list associations
list2params proc
params var (world)
text2num proc
Format:
params2list(Params)
Args:
Params: Text string of parameter values.
Returns:
An associative list of parameter names and values.

This instruction converts a parameter text string to a list of individual parameters and associated values. The format of the parameter text is:

"name1=value1&name2=value2&..."

The field separator ; may be used in place of &.

Special characters such as =, ;, and & inside the parameter names or values should be written in the form %xx, where xx are two hexadecimal digits representing the ASCII value of the character. (For Unicode characters, this may be several %xx sequences using UTF-8 encoding.) For example, = would be written %3d, ; would be %3b, & would be %26, and % would be %25. These "escaped" codes are automatically translated into the corresponding character when read by params2list().

This parameter format is the same one used by most HTML forms and is known by the MIME type application/x-www-form-urlencoded. It is often used in DM to pack information into topic links. Though DM does not require it, the standard format is for newlines to be written as CR LF pairs (%0d%0a) and spaces to be written as + characters. That means if you want to write a + symbol, you will have to use %2b.

The list produced from the parameter text has items "name1", "name2", and so on. To access the values associated with these, you use the parameter name as the list index.

Example:

var/ptext = "offense=jwalk&time=10:00" var/plist[] = params2list(ptext) var/p for(p in plist) usr << "[p] = [plist[p]]"

The above example defines a simple parameter text string containing two parameters: "offense" and "time". These are associated with the values "jwalk" and "10:00". The for loop illustrates how one might loop through the list and print out each setting.

Note that all values are stored as text strings in the list. If you wish to perform a numerical operation (such as addition), you should convert the value to a number first using text2num(). If the value is an object text reference, you can convert that into the object itself by using locate().

If you have multiple items with the same name, they will be combined into a list of text strings. For example, "key=value1;key=value2" would set list["key"] to a list containing "value1" and "value2", not necessarily in that order.


pick proc

See also:
prob proc
Format:
pick(Val1,Val2,...)
pick(List)
Returns:
One of the given values randomly chosen.

Randomly chooses an item from a list or from the arguments provided. If only one argument is included and it is a list, then the item is chosen from that list.

When not using the list form, you can make a particular value more or less likely to be chosen by providing a relative probability like this:

prob(P); Val Or P; Val

A value for P of 200 makes it twice as likely as the norm, 50 half as likely, and so on.

Example:

obj/food verb/eat() usr << pick ( "[usr] eats \a [src].", prob(50) "[usr] devours \a [src].", prob(25) "[usr] wolfs down \a [src]." ) del(src)

There is no analogous weighted format for the list version of this proc.


prob proc

See also:
pick proc
rand proc
rand_seed proc
roll proc
Format:
prob(P)
Returns:
1 with probability P percent; otherwise 0
Args:
P: A number.

rand proc

See also:
pick proc
prob proc
rand_seed proc
roll proc
Format:
rand(L=0,H) or rand()
Returns:
A random integer between L and H inclusive; or a random number from 0 up to 1 if L and H are omitted.
Args:
L: A number for the lower-bound.
H: A number for the upper-bound.

rand_seed proc

See also:
pick proc
prob proc
rand proc
roll proc
Format:
rand_seed(Seed)
Args:
Seed: An integer used to initialize the random number generator.

Many DM procedures make use of a pseudo-random number generator. You can use rand_seed() to initialize the generator. The sequence returned by the generator is identical each time it is initialized with the same seed, so you could use this to reproduce the same output from an algorithm that uses the random number generator. If you never call rand_seed(), the generator is initialized with a seed from the system clock, so it is effectively random.

Note that with multiple realtime algorithms making calls to the generator at unpredictable times, you are likely not to get the same result even when using the same seed. The overall sequence will be the same, but individual sub-components of your world might call it in a different order.

The pseudo-random number generator is system dependent, so do not expect the sequence generated from a particular seed to be identical on two different machines or operating systems.


range proc

See also:
<< output operator
block
view proc
orange proc
Format:
range(Dist,Center=usr)
Returns:
A list of objects within Dist tiles of Center.
Args:
Dist: A number.
Center: An object on the map.

This instruction is identical to view() except visibility is ignored. All objects are included in the list whether they are visible or not.

A Dist of 0 includes Center, the contents of Center (normally usr.contents), its location (normally the turf a mob is standing on), and any other contents of that location. A value of 1 extends the region to the neighboring squares on the map and so on. You can also use a rectangular box size using a text string such as "13x11". Both arguments are optional and may be passed in any order.


ref proc

See also:
\ref text macro
locate proc
Format:
ref(Object)
Args:
Object: The object to get a reference for
Returns:
A string containing a reference ID.

This is a shortcut for "\ref[Object]".


refcount proc

See also:
garbage collection
Format:
refcount(Object)
Args:
Object: The object to get a reference count for
Returns:
A count of references for the object.

This gets a reference count for a value, not including the reference that was placed on the stack while evaluating this proc.

A return value of 0 can mean one of several things: Either this was the last reference and the object was subsequently deleted after refcount(), or the value doesn't support reference counting.

Note: A nonzero return value does not necessarily mean the object will be deleted when its count reaches zero; mobs for instance will not be soft-deleted by the garbage collector if their key var is set, and some objects like clients and areas never soft-delete. A zero value also does not necessarily mean the object is immortal; it may be transient, like the args list in a proc that only lives as long as that copy of the proc lives.


regex proc

See also:
Regular expressions
regex datum
regex procs
findtext proc
replacetext proc
splittext proc
REGEX_QUOTE proc
Format:
regex(pattern, flags)
regex(Regex)
Returns:
A new /regex datum.
Args:
pattern: The pattern string to search for
flags: (optional) A text string containing any combination of modifier flags
Regex: an existing /regex datum to copy

Creates a regular expression, stored in a /regex datum, that can be used for searching and/or replacing text.


REGEX_QUOTE proc

See also:
regex proc
regex datum
stddef.dm file
Format:
REGEX_QUOTE(text)
REGEX_QUOTE_REPLACEMENT(text)
Returns:
REGEX_QUOTE: A version of the text with any special regular expression characters escaped by backslashes.
REGEX_QUOTE_REPLACEMENT: A version of the text with $ characters escaped by a second $.
Args:
text: The text to escape

Quotes a piece of text so that it can be used inside a regular expression without fear of being treated as pattern instructions.

Example:

proc/FindWord(text, word) // The \b pattern is a word break, to search for the word // on its own instead of as part of another word. var/regex/R = regex("\\b[REGEX_QUOTE(word)]\b", "i") // find the pattern in the text return R.Find(text)

replacetext proc

See also:
findtext proc
replacetextEx proc
Regular expressions
Replace proc (regex)
Format:
replacetext(Haystack,Needle,Replacement,Start=1,End=0)
Returns:
The Haystack text with all cases of Needle replaced by Replacement
Args:
Haystack: The text string to search.
Needle: The sub-text to search for. May be a regular expression (regex).
Replacement: The replacement text, or a proc.
Start: The text byte position in Haystack in which to begin the search.
End: The text byte position in Haystack immediately following the last character to search.

When Needle is text, this instruction is NOT sensitive to the case of Haystack or Needle. The case-sensitive version is replacetextEx(). If the Needle is a lowercase word, the replacement will be changed to uppercase or all caps if the found text is uppercase or all caps.

Example:

world << replacetext("One on one", "one", "two")

This outputs "Two on two", where the first case's "One" is identified as uppercase.

You may use a proc as the Replacement value. In that case, the proc will be called with the found text as an argument, and its return value will be the replacement. There will be no automatic correction to uppercase or all caps in this case.

When the Needle value is a regular expression, this proc behaves identically to the regex Replace() proc. Case-sensitivity, and whether one match or all are replaced, depend on the regular expression.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use replacetext_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


replacetextEx proc

See also:
findtextEx proc
replacetext proc
Regular expressions
Replace proc (regex)
Format:
replacetextEx(Haystack,Needle,Replacement,Start=1,End=0)
Returns:
The Haystack text with all cases of Needle replaced by Replacement
Args:
Haystack: The text string to search.
Needle: The sub-text to search for. May be a regular expression (regex).
Replacement: The replacement text, or a proc.
Start: The text byte position in Haystack in which to begin the search.
End: The text byte position in Haystack immediately following the last character to search.

When Needle is text, this instruction is sensitive to the case of Haystack and Needle. The case-insensitive version is replacetext().

Example:

world << replacetext("One on one", "one", "two")

This outputs "Two on two", where the first case's "One" is identified as uppercase.

You may use a proc as the Replacement value. In that case, the proc will be called with the found text as an argument, and its return value will be the replacement. There will be no automatic correction to uppercase or all caps in this case.

When the Needle value is a regular expression, this proc behaves identically to the regex Replace() proc. Case-sensitivity, and whether one match or all are replaced, depend on the regular expression.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use replacetextEx_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


return statement

See also:
. var (proc)
Format:
return E

Stop execution of the current proc and return the value of E to the caller. If no value is specified, the value of . will be returned, which defaults to null.


rgb proc

See also:
rgb2num proc
gradient proc
Color space
HTML colors
color var (atom)
Blend proc (icon)
Color matrix
Color matrix filter
Particle effects
Format:
rgb(R,G,B)
rgb(R,G,B,A)
rgb(x,y,z,space=color space)
rgb(x,y,z,a,space)
Args:
R,G,B: Numbers from 0-255 corresponding to the red, green, and blue components of a color.
A: Optional alpha component; 0 is transparent, 255 is opaque.
x,y,z: Color components for a different color space
space: Color space; defaults to COLORSPACE_RGB
Returns:
A color, represented by a text string in #RRGGBB or #RRGGBBAA format

A way of representing a color to be used in conjunction with icon arithmetic, atom.color, or other effects. The colors rgb(0,0,0) and rgb(255,255,255) represent black and white, two corners of the "color cube".

Example:

mob/proc/hurtme() // make a mob look damaged by adding red to its icon src.icon += rgb(20,0,0)

This proc returns a text string in the form used by HTML (#RRGGBB). rgb(255,0,128) for example becomes "#ff0080". If you use an alpha component, the format is #RRGGBBAA. You can use strings like this in most procs that use colors such as icon blending operations, and you can also use the short form #RGB or #RGBA. So if you know in advance that you want to use the color white, you can simply use"#fff" instead of rgb(255,255,255).

You can create colors other ways by specifying a different color space. A color space can be specified by using a named "space" argument, or by using a 5-argument format (you can leave the alpha value blank or null to skip it), or by using named arguments for the other components.

Example:

// All of these lines are equivalent. // They create (0,100,50) in HSL which is red (#ff0000). src << rgb(0, 100, 50, space=COLORSPACE_HSL) src << rgb(0, 100, 50, , COLORSPACE_HSL) src << rgb(h=0, s=100, l=50)

Named arguments that are valid in rgb() are:

With the exception of space, only the first letter of the argument name matters, so r and red are the same thing.


rgb2num proc

See also:
rgb proc
gradient proc
Color space
HTML colors
Format:
rgb2num(color)
rgb2num(color, space)
Args:
color: A color value (see HTML colors)
space: Color space; default is COLORSPACE_RGB
Returns:
A list with the components of this color

Parses a color into a list with 3 or 4 component values; the 4th value is alpha, if it's part of the color provided.

Example:

var/list/RGB = rgb2num("#ff8000") src << RGB[1] // red (255) src << RGB[2] // green (128) src << RGB[3] // blue (0)

By specifying a different color space, you can convert a color into a different format.

Example:

var/list/HSL = rgb2num("#5af", COLORSPACE_HSL) src << HSL[1] // hue (210) src << HSL[2] // saturation (100) src << HSL[3] // luminance (66.6667)

roll proc

See also:
rand proc
Format:
roll(ndice=1,sides)
roll(dice)
Returns:
The sum of the rolled dice.
Args:
ndice: number of dice to role.
sides: number of sides to the dice.
dice: a text string encoding both ndice and sides (see below).

The sides of the dice are numbered 1 through the total number of sides and each is equally likely.

An alternate form takes the dice parameters in a single text value such as "3d4". This may be useful when you want to store the dice information in a single variable. You can even specify an offset, such as "3d4+5". That adds 5 to the sum of 3 dice having 4 sides each.

Example:

obj/potion/healing var/dice = "3d6" verb/drink() var/h = roll(dice) if(h>15) usr << "Very refreshing!" else usr << "You feel better."

round proc

See also:
floor proc
ceil proc
trunc proc
fract proc
Format:
round(A)
round(A,B)
Returns:
rounded A
Args:
A: A number.
B: The nearest multiple to round A.

The first format returns the floor of A (the largest integer less than or equal to A), and has been deprecated in favor of floor(A). The second format rounds A to the nearest multiple of B.

Example:

usr << round(1.45) // outputs 1 usr << round(-1.45) // outputs -2 usr << round(1.45,1.5) // outputs 1.5

run proc

See also:
<< output operator
file proc
link proc
Format:
O << run(File)

This is similar to link() but instead of a URL, you can pass a file to be viewed directly. The file may be a cache file or an external file.

Example:

mob/var/picture = 'mob.jpg' mob/verb/view_pic(mob/M as mob in view()) usr << run(M.picture) mob/verb/set_pic(F as file) usr.picture = F

This example defines a picture to be associated with each mob and a verb for viewing another mob's picture. Players can also configure their own pictures.


settings (proc)

proc settings:

verb/set
  name
  desc
  category
  hidden
  popup_menu
  instant
  invisibility
  src
  background
  waitfor

Procs and verbs are the same "type" so these attributes may be set for both procs and verbs; most of them only apply to verbs, so they only take effect if the proc is invoked as a verb (by adding it to a verb list).


background setting (proc)

See also:
sleep proc
spawn proc

To avoid lag from procedures that hog the CPU for too long, you can turn on background processing. This will cause it to periodically sleep for long enough to allow other events to be processed.

The following example is a typical "ticker" procedure. It spawns off an infinite loop which does some work and then sleeps before iterating again. By running this in the background, you ensure that the work being done does not create large delays. You could achieve a similar thing by sprinkling calls to sleep(0) or sleep(-1) in the "working" part of the loop.

Example

proc/Ticker() set background = 1 spawn while(1) for(var/mob/M in world) M.Tick() sleep(10)

Since the background procedure sleeps at unpredictable times, you must be aware that race conditions are possible if the background procedure interacts with variables modified by other procedures. It's still much safer than multi-threaded programs because the background procedure never interrupts other code; but other code may interrupt the background procedure.

Note that procedures that are called by the background procedure do not automatically run in the background unless they too have the background setting turned on. For instance, the code in the above example does not imply that the mob Tick() procs would run in the background. This is convenient, because you should only ever apply background processing to code after checking that there are no potential race conditions involved.

If you have an eye for race conditions, you might think that the above code has one in which a mob gets deleted after it is assigned to M but before the call to M.Tick() is executed. However, background processing is only interrupted at loop points in the code, so the above code is safe. It would only ever be interrupted at the end of the for or while loops.


waitfor setting (proc)

See also:
sleep proc
spawn proc
. var (proc)

By default, procs that sleep usually expect their callers to wait for them to finish, so the callers must sleep as well. Using set waitfor=0 will disable that behavior, causing any sleep to return control to the caller immediately.

Example

mob/proc/LongLoop() set waitfor = 0 while(1) UpdateAI() // proc will return to caller here sleep(1)

This setting will also dictate what happens if a callee sleeps. Consider an example where proc A calls proc B which calls proc C, and proc B has waitfor set to 0. When proc C sleeps, proc B will also sleep, but proc A will continue running as if proc B returned early. The . var currently in proc B will be used as its return value to A. When proc C wakes up and finishes, it will wake up proc B, but now B's return value will be ignored since A is no longer waiting for it.

In older versions, the New proc always had waitfor set to 0 by default, but this was later changed. Now 1 is always the default, so setting waitfor to 1 will result in a warning that it is no longer necessary.


sha1 proc

See also:
md5 proc
file proc
Format:
sha1(T)
sha1(F)
Returns:
text or null.
Args:
T: A text string.
F: A file.

This proc implements SHA1 hashing. A hash function is a one-way process that compacts information to a short value: a hash. The same value will always have the same hash. Among other uses, most computers use hashing to store passwords. By storing just the hash, the password file contains very little sensitive information, but the password can still be verified by confirming that sha1(password)==hash. SHA1 is a widely-used hash function.

Example:

mob/var/hash mob/Read(savefile/S) ..() // hash was saved in the file along with other values if(sha1("[level]/[exp]/[exp_needed]") != hash) src << "Cheater!" del(src)

In the example, a few vars belonging to a mob were saved along with a hash of those values. When the mob is loaded again, the game compares the hash to the values to make sure it's still accurate. If the values or hash had been changed by a sneaky player, they wouldn't match. (But a sneaky player could still calculate hash themselves if they knew the exact text used to make it, so this should be kept secret.)

If the argument is a file, sha1() will read the file and return the SHA1 hash of the file's entire contents. If the file doesn't exist, it returns null. The file may be a cache file or an external file.

Examples:

var/hash = "(insert hash value here)" // Compute this ahead of time // Check that the cached default icon is still the same if (sha1('default.dmi') != hash) world << "The default icon has been modified!" // Or check that the entire game resource file is pristine if (sha1(file("mygame.rsc")) != hash) world << "The game resources have been modified!"

Note that you must pass the result of file() in order to compute the hash of an external file's contents at runtime. Otherwise sha1() will treat the filename as text and return the hash of the name only.

If T is anything but a text string or file, the proc returns null.


shell proc

See also:
fcopy proc
fdel proc
file2text proc
process var (world)
system_type var (world)
text2file proc
Format:
shell(Command)
Args:
Command: system command to run
Returns:
null on failure to execute command
exit code of command otherwise

This function is used to run an external program. The syntax of Command depends on the server machine's operating system. Be sure to redirect input and output to files if there is any. Also realize that the command will fail if the program you try to run is not in the path where the shell expects to find executable files (unless you specify a full path).

Since shell() allows arbitrary access to the system, each call requires authorization from the person hosting the world, unless running in trusted mode. Authorization is only sought when running in Dream Seeker, since Dream Daemon is intended to be non-interactive. Calling shell() with no arguments is a way of checking if it is allowed by the current safety settings. It will return true if running in Dream Seeker (regardless of safety mode) or if running in Dream Daemon in trusted mode.

The calling proc will sleep until the command is finished executing.

Example:

mob/verb/dir(Path as text) shell("dir [Path] > dir.out") usr << file2text("dir.out")

This example displays the output of the "dir" command to the user.


shutdown proc

See also:
Export proc (world)
startup proc
Format:
shutdown(Addr,Natural=0)
Args:
Addr: This is the address of the child world returned by startup().
Natural: Specifies whether to wait for the child world to die naturally, or whether it should be killed with the "Del" world topic. The default value of 0 kills the child, and a value of 1 waits for the child to exit of its own accord.

If no address is specified, the current world is shut down.


sin proc

See also:
arcsin proc
cos proc
tan proc
turn proc
Format:
sin(X)
Returns:
The sine of X, where X is in degrees.

Example:

mob/verb/test() usr << sin(0) // 0 usr << sin(45) // 0.707... usr << sin(90) // 1

sleep proc

See also:
background setting (proc)
waitfor setting (proc)
spawn proc
tick_lag var (world)
Format:
sleep(Delay)
Args:
Delay: The amount of time to sleep, in 1/10 seconds.

Pause the current proc (and its callers) for a specified amount of time. If no delay is specified, it will be scheduled to resume as soon as other immediately pending events are processed.

Note that sleeping in some procedures results in the return value being lost. For example, if you sleep inside Entered() or Exited(), it will be as if you returned immediately where you started sleeping. This is because Move() calls them in away that says the return value should be ignored. Also if a proc has its waitfor setting changed to 0, it will return the value of the . var to its caller immediately if it or one of its callees sleeps.

Also be aware that a sleeping procedure whose src object gets deleted will automatically terminate when execution returns to it. This is to protect you against trying to access properties or procedures of a deleted (and therefore null) object. If you do not want the procedure to be terminated, you should set src to null.

One common use of sleep is to create what is known as a ticker. That is an infinite loop that performs some periodic operation.

Example:

proc/Weather() spawn while(1) //infinite ticker loop world << "The sun rises in the east." sleep(500) world << "The noon day sun rises high in the sky." sleep(500) world << "The sun sinks low in the west." sleep(1000)

Notice how such infinite loops are usually created using spawn to prevent the caller from getting locked up. You could call this procedure from world.New() to start it rolling.

Note: sleep time is in 1/10s units, not server ticks. If your world.tick_lag or world.fps value is different from the default, sleep(1) still means "sleep for 1/10s". To sleep for exactly N ticks, call sleep(N * world.tick_lag).

If the ticker does intensive processing during each iteration, you probably want to run it in the background like this:

proc/Ticker() set background = 1

Calling sleep() with a negative argument (such as sleep(-1)) causes it to do a backlog check. Only if other pending events have become backlogged will it sleep. This is similar to running in the background, but you manually control where the backlog checks are made. The difference between this and sleep(0) is that sleep(0) always sleeps the current procedure for as short a time as possible, whereas sleep(-1) only sleeps the current procedure if other scheduled events have become backlogged. Therefore, sleep(-1) will tend to run the current procedure at a higher priority with fewer interruptions. It is appropriate when there is a single task that needs to be done before anything else can happen, and you just want to make sure that network and user I/O are not terribly lagged in the process.


sorttext proc

See also:
> operator
< operator
sorttextEx proc
Format:
sorttext(T1,T2,...)
Args:
Any number of text strings to sort.
Returns:
1 if text is ascending
-1 if text is descending
0 otherwise

This instruction is NOT sensitive to case. The case sensitive version is sorttextEx().

Example:

switch(sorttext("A","B")) if(1) world << "ascending" if(-1)world << "descending" if(0) world << "neither"

This outputs "ascending", since "A" comes before "B" in the alphabet.


sorttextEx proc

See also:
> operator
< operator
sorttext proc
Format:
sorttextEx(T1,T2,...)
Args:
Any number of text strings to sort.
Returns:
1 if text is ascending
-1 if text is descending
0 otherwise.

This instruction is sensitive to case. The case-insensitive version is sorttext().

Note: Uppercase letters are lower in the alphabetical order than lowercase letters.

Example:

switch(sorttextEx("a","B")) if(1) world << "ascending" if(-1)world << "descending" if(0) world << "neither"

This outputs, "descending", since "B" comes before "a" in the alphabet.

Note: This proc used to be named sortText, like sorttext but with a capital T. To avoid confusion it has been renamed, but old code will still compile.


sound proc

See also:
sound datum
vars (sound)
<< output operator
load_resource proc
Format:
sound(file,repeat=0,wait,channel,volume)
(supports named arguments)
Args:
file: A sound file to play
repeat: 1 to play sound repeatedly
wait: 0 to interrupt current sound on channel; 1 to wait in queue
channel: 0 for any available channel, 1-1024 for specific channel (non-MIDI only)
volume: 100 for full volume (default), 0 for none, or any value in between

This is used to play a sound file.

The sound file must be a music or sample file. Music files include MIDI (.mid or .midi), and module formats .mod, .it, .s3m, .xm, and .oxm. A sample file used for sound effects can be .wav, .ogg, .raw, .wma, or .aiff.*

The following example plays some sound files. Note that sound() is not even necessary when you don't need to set any additional parameters.

Example:

usr << 'giggle.wav' // play a giggle once usr << sound('gigue.midi',1) // repeat gigue usr << sound('boom.wav', volume=50) // play an explosion at half volume

*See Notes under sound support for more information.


spantext proc

See also:
findtext proc
nonspantext proc
splittext proc
Format:
spantext(Haystack,Needles,Start=1)
Returns:
The number of consecutive characters, from the start position, that match the characters in Needles.
Args:
Haystack: The text string to search.
Needles: A text string with all the characters that match.
Start: The text byte position in Haystack in which to begin the search.

This proc is case-sensitive. A common use for this proc is in parsing. spantext("apples, oranges",", ",7) will tell you that, starting at position 7, you need to skip 2 characters to get past any commas or spaces.

If the start position is negative, the position is counted backwards from the end of the string.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use spantext_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


spawn proc

See also:
background setting (proc)
sleep proc
Format:
spawn(Delay=0) Statement
spawn(Delay=0)
Statement
Args:
Delay: The amount of time (in 1/10 seconds) before Statement is executed.

Run Statement after a delay. Statement may be a single statement or a code block enclosed in (optional) braces and indented. If delay is negative, the spawned code is executed before continuing in the main code. If it is zero, the spawned code is scheduled to happen right after other existing events that are immediately pending.

Example:

spawn(30) storm() usr << "Storm clouds are brewing!"

This will display "Storm clouds are brewing!" and then call the storm() proc after 3 seconds.

The important feature of spawn() is that the caller does not have to wait around for the spawned code to finish.

Any vars you have defined in the proc itself, including arguments, will be copied between the spawned code and the code that runs right away. This means that if one part modifies one of those vars, the other part will not see that change. Changes made to objects, lists, datums, etc. however will be visible to both code blocks.

Pointers to any vars that belong to the proc will stay with the original proc, not the copy.


splicetext proc

See also:
copytext proc
Splice proc (list)
Format:
splicetext(Text,Start=1,End=0,Insert="")
Returns:
Spliced text
Args:
Text: The text string to splice.
Start: The text byte position in Text where the splice will begin.
End: The text byte position in Text immediately following the last character to be cut from the splice. 0 is the end of the string.
Insert: Text to be inserted.

Cuts out a section of a text string and inserts a different piece of text in its place. This is basically equivalent to copytext(Text,1,Start) + Insert + copytext(Text,End), but faster.

Example:

// cuts "nan" from "banana" and replaces it with "laclav" // prints "balaclava" usr << splicetext("banana", 3, 6, "laclav")

The Start and End index values can be negative, which count backwards from the end of the string. If the index values are out of range, there will be no error; they will simply be clamped to the beginning or end of the string. If End comes before Start, the two values are swapped.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use splicetext_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


splittext proc

See also:
findtext proc
jointext proc
nonspantext proc
spantext proc
Regular expressions
Format:
splittext(Text,Delimiter,Start=1,End=0,include_delimiters=0)
Returns:
A list of text strings split by the delimiter given.
Args:
Text: The text string to search.
Delimiter: A text string that will be used as the separator between items, OR a regular expression (regex) used to find splits
Start: The text byte position in Text in which to begin looking for splits.
End: The text byte position in Text immediately following the last character to look at for splits.
include_delimiters: True if any delimiters found should be included in the result.

Splits up a text string and returns a list. The delimiter is case-sensitive (unless you use a case-insensitive regular expression), and can be more than one character long.

Example:

var/list/items = splittext("apples,oranges,bananas", ",") // prints "apples", "oranges", and "bananas" separately for(var/item in items) usr << item

Where multiple delimiters are next to each other, they're considered to be separating an empty string. Therefore splittext("a,,b,c", ",") would return a list with four elements instead of three. Splitting empty text returns an empty list.

If a regular expression is used as the delimiter, any capturing groups in the expression will be included in the list, in order. (The whole match itself will come first, if include_delimiters is true.) So for instance splitting by regex(",") will not include the comma, but splitting by regex("(,)") will. Groups that were not part of the match will be null.

If the start or end position is negative, the position is counted backwards from the end of the string. Please note that the start and end positions do NOT trim the string; if you want to split a trimmed string, trim it with copytext() and send the result to splittext() instead.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use splittext_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


sqrt proc

Format:
sqrt(A)
Returns:
The square root of A
Args:
A: A number.

Example:

usr << sqrt(2) // outputs 1.41421

startup proc

See also:
params var (world)
shutdown proc
Format:
startup(File,Port=0,Options,...)
Args:
File: The dmb file to run in a new server or null to load the current world.
Port: The network port to start the new server on. A value of 0 indicates that any available port should be used.
Options: Any number of the options listed below. Each option should be in an argument by itself. If the option takes a parameter, this can be in the same argument or in the following one.

The valid options are:

-once
automatically shuts down the server when all players have logged off.
-close
Closes the child copy of DreamDaemon after the world it is running shuts down.
-log <logfile>
sends all server output to the specified file. The path to the file is relative to the world directory (the path containing the world .dmb file).
-logself
is identical to "-log [YourWorldFile].log".
-safe
runs the server in a special protective mode. The server may only access files in the same directory (or below) as the dmb file and access to the shell() command is disabled. This is the default mode if no security setting is specified and the world is run from a directory by the same name as the dmb file.
-home <path>
runs with the specified "safe home" directory. Normally, in safe mode the directory containing the world dmb file is the safe home.
-ultrasafe
like -safe, this prohibits all file access. This is the default if no security mode is specified and the world is not run from a directory with the same name.
-trusted
allows full access to files on the computer and to the shell() command. Note that this does not bypass the normal security of the operating system. For example, in the UNIX operating system, all of the usual access restrictions apply. This mode merely removes BYOND's built-in safety checks.
-params <paramtext>
this is for passing user-defined parameters to the world. Multiple parameters may be packed into a single argument or -params may be used several times. In either case, the parameters are all loaded into world.params when the world starts up. The parameter format is "name1=value1&name2=value2&...".
-quiet
disables the server's normal output indicating the BYOND version number and network port.
-nologdates
disables automatic date/time output in the log.
-CGI
runs the world as a CGI program (to be executed by a web server). A /client object is automatically created for the user and any output sent to the associated mob gets returned to the user's web browser. This option is normally specified in the compile-time setting: world.executor, which is automatically initialized for you if you include html/CGI.dm from the html library.
-suid <path>
runs the world as the owner of the specified directory or path. This only works if DreamDaemon is running as root on operating systems where there even is such a thing.
-suidself
runs the world as the owner of the world dmb file. This only works if DreamDaemon is running as root on operating systems where there even is such a thing.
-cd <path>
runs with the specified working directory. Normally, the directory containing the world dmb file is used.
-port P
sets the network port to P. The port may also be specified as a positional argument (following the .dmb name).
-ports <list>
restricts the range of ports that DreamDaemon and any child worlds may use. The syntax of list is a comma separated list of ports or ranges of ports. Example: -ports 1234,1236,1240-1250.
-ip <address>
sets the IP address of the server. This will only work for an IP address the system recognizes as one it can use for hosting. Accepts numerical addresses only.
-webclient
Enables the webclient, overriding default behavior.
-nowebclient
Disables the webclient, overriding default behavior.
-verbose
Runtime errors will continue outputting details after a certain number of errors has been reached. Without this option, the number of errors that provide detailed info (such as call stack) is limited. Use this option with caution as it could fill up a log file quickly if a problem occurs.
Returns:
The address of the new server in the form ip:port.

stat proc

See also:
Stat proc (atom)
Stat proc (client)
statpanel proc
Info control (skin)
Format:
stat(Name,Value)
Args:
Name: the name of the stat line
Value: the data to be displayed

This is used in a Stat() proc to send a stat line to usr, the person looking at an object. A stat line has an optional name part which must be unique for each stat line (or successive calls will replace previous ones).

The stat line gets appended to the current stat panel. The current panel may be changed by using statpanel().

If no name is specified and the value is a list, this is the same as calling stat on each item in the list. This can be used (in conjunction with statpanel) to create an inventory panel or something similar.

Example:

mob/Stat() stat("description",src.desc) if(src == usr) stat(src.contents)

This example displays the mob's description and inventory all in one panel. The code ensures that only the mob may see his own inventory, but you don't have to worry about that unless you change client.statobj to something other than one's own mob.


statpanel proc

See also:
Stat proc (atom)
Stat proc (client)
stat proc
Info control (skin)
Format:
statpanel(Panel,Name,Value)
Args:
Panel: the name of the stat panel
Name: the name of the stat line
Value: the data to be displayed
Returns:
If called with just a Panel argument, 1 is returned if the player is looking at the panel and 0 is returned if not. This may be useful to avoid the needless overhead of generating output to a panel that is not visible.

This is used in a Stat() proc to change the default panel (for subsequent stat lines) or to send one line to the specified panel. Name and Value are both optional. If neither is specified, this simply changes the default panel. Otherwise, the default panel is unchanged and a stat line is appended to Panel.

Example:

mob/Stat() stat("description",src.desc) if(src == usr) statpanel("inventory",src.contents)

This example displays the mob's description in one panel and inventory in another. Only the mob may see his own inventory, but you don't have to worry about that unless you change client.statobj to something other than one's own mob.


step proc

See also:
get_step proc
walk proc
step_size var (movable atom)
Format:
step(Ref,Dir,Speed=0)
Returns:
1 on success; 0 otherwise
Args:
Ref: A mob or obj.
Dir: One of NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref in the direction Dir.


step_away proc

See also:
get_step_away proc
walk_away proc
step_size var (movable atom)
Format:
step_away(Ref,Trg,Max=5,Speed=0)
Returns:
1 on success; 0 otherwise.
Args:
Ref: A mob or obj.
Trg: An object on the map.
Max: The maximum distance between Ref and Targ before movement halts.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref on a path away from location Trg, taking obstacles into account. If Ref is farther than Max steps from Trg, no action will be taken.


step_rand proc

See also:
get_step_rand proc
walk_rand proc
step_size var (movable atom)
Format:
step_rand(Ref,Speed=0)
Returns:
1 on success; 0 otherwise.
Args:
Ref: A mob or obj.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref randomly.


step_to proc

See also:
get_step_to proc
get_steps_to proc
walk_to proc
step_size var (movable atom)
Format:
step_to(Ref,Trg,Min=0,Speed=0)
Returns:
1 on success; 0 otherwise.
Args:
Ref: A mob or obj.
Trg: An object on the map.
Min: The minimum distance between Ref and Trg before movement halts.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref on a path to the location Trg, taking obstacles into account. If Ref is within Min steps of Trg, no action will be taken. This is also the case if the target is too far away (more than twice world.view steps).


step_towards proc

See also:
get_step_towards proc
walk_towards proc
step_size var (movable atom)
Format:
step_towards(Ref,Trg,Speed)
Returns:
1 on success; 0 otherwise.
Args:
Ref: A mob or obj.
Trg: An object on the map.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref in the direction of the location Trg.


switch proc

See also:
if proc
Format:
switch(E)
if(A1,A2,...) Statement1
if(B1,B2,...) Statement1
else Statement3

The "switch" instruction is a compact notation for a lengthy "else-if" chain. The expression E is compared to the values A1, A2, B1, B2, etc. When a match is found, the following statement (or code block) is executed. An optional "else" statement is run if no match is found. Once a matching switch condition is found, no further conditions will be tested.

The values A1, A2, etc. must be constants. As a convenience, a range of values may be specified in the form: A1 to An.

The switch instruction is MUCH more efficient than a lengthy "else-if" chain, because the expression E is evaluated only once. The conditional values may be any constant expression, such as a number or text string.

Example:

switch (2) if(1) world << "ONE" if(4) world << "FOUR" if(2,3) world << "TWO or THREE" if(5 to 10) world << "FIVE to TEN" else world << "not ONE to TEN"

This outputs:

TWO or THREE

Note: Currently the compiler does not throw a warning or error if there is a conflict between two different if blocks in a switch, e.g. when you define if(1 to 10) and if(5 to 20) which overlap from 5 to 10. If two different blocks could handle a given value, the choice of which block takes over is not defined.


tan proc

See also:
arctan proc
cos proc
sin proc
turn proc
Format:
tan(X)
Returns:
The tangent of X, where X is in degrees.

Example:

mob/verb/test() usr << tan(0) // 0 usr << tan(45) // 1 usr << tan(90) // infinity (or close enough)

text proc

See also:
<< operator
macros (text)
Format:
text(FormatText,Args)
Returns:
The text with macros arguments substituted.
Args:
FormatText: a text string possibly containing text macros.
Args: a set of arguments that corresponds to the number of empty embedded expressions in FormatText.

Complicated or lengthy embedded expressions in a text string can sometimes make the string difficult to read. In this case, one can use trailing arguments. The position in which the expression should be substituted should be marked with [] and the expression should then be passed as an argument after the text string.

Example:

usr << text("You are [] leagues from home.",sqrt(usr.x**2 + usr.y**2))

text2ascii proc

See also:
ascii2text proc
entities (text)
Unicode
Format:
text2ascii(T,pos=1)
Args:
T: A text string.
pos: The byte position in T to use, starting at 1.
Returns:
A number representing the character's ASCII or Unicode code.

ASCII codes are numerical values corresponding to keyboard and special characters. Among other things, they are used to represent many symbols in HTML. This proc converts a text string to its corresponding ascii representation.

Example:

world << text2ascii("A") // = 65 world << text2ascii("HAPPY",2) // = 65

With Unicode, things may get more complicated. DM stores text with UTF-8 encoding, so at this position there might be several bytes strung together to make a single character. The value of pos is in bytes, not characters. When the return value is 128 (0x80) or higher, multiple bytes are used for the charcter. In that case the next character position is not pos + 1 like it is for regular text, but you can use pos + length(ascii2text(result)) instead. Or, you can determine the byte count from this table:

Character codeSize in bytes
0 - 0x7F1
0x80 - 0x7FF2
0x800 - 0xFFFF3
0x10000 - 0x10FFFF4

Alternatively, you can use test2ascii_char() to work with character positions instead of bytes, at a performance cost.


text2file proc

See also:
file2text proc
shell proc
Format:
text2file(Text,File)
Args:
Text: text to be added to file
File: file to be appended to
Returns:
1 on success; 0 otherwise.

Appends text to a file. If the file does not exist, one will be created.

This can be useful when interacting with external applications that read output from a text file. For example, you might have an external program that mimics conversation:

Example:

mob/oracle/verb/tell(T as text) text2file(T,"oracle.in") shell("oracle < oracle.in > oracle.out") usr << file2text("oracle.out")

text2num proc

See also:
istext proc
num2text proc
Format:
text2num(T)
text2num(T, radix)
Args:
T: A text string.
radix: The radix/base of the number, e.g. 16 for hexadecimal
Returns:
A number.

If T is a text string for a number, return the number. Any non-numeric text following the initial portion will be ignored. If there is no initial numeric portion, the result is null.

Example:

var/number = text2num("123") // = 123

The optional radix, which defaults to 10, can be any integer from 2 to 36.


text2path proc

See also:
ispath proc
Format:
text2path(T)
Args:
T: A text string.
Returns:
a type path or null.

Example:

var/myturf = text2path("/turf/[src.color]") if(myturf) src.loc = locate(myturf)

T is changed from a text string to the equivalent type path, or null if there is no such type.


throw statement

See also:
try statement
Error proc (world)
EXCEPTION proc
exception
Format:
throw Value
Args:
Value: Any value, which will be sent to catch() if present.

This keyword throws an exception, which will stop executing the current proc and go to the most recent catch block if one is present. The catch block will receive the thrown value. If there is no try/catch in use, the exception will be passed to world.Error() (if present), then the current proc will end and control will return to the caller.

Example:

try if(!src.ready) throw EXCEPTION("Not ready") DoSomething() catch(var/e) world.log << "Exception: [e]"

You can use the EXCEPTION macro to create a new /exception datum, which contains a value or message as well as the file and line number where the exception was created. The thrown value does not have to be an /exception datum; you can throw anything, even null.


time2text proc

See also:
realtime var (world)
timeofday var (world)
timezone var (world)
timezone var (client)
Format:
time2text(timestamp,format,timezone)
Args:
timestamp: a time value as obtained from world.realtime or world.timeofday
format: a text string describing the output format.
timezone: optional offset, in hours, from UTC
Returns:
a text string containing the date and time in the specified format.

A time value (UTC) is converted to text representing the time. The world's local time is used, unless you specify a timezone argument which will add an offset to UTC.

The default format is "DDD MMM DD hh:mm:ss YYYY", which produces results such as "Wed, May 23 15:41:13 2001". As you can see, the fields in the format text are replaced by components of the date and time. The following list contains all of the recognized fields. Anything else in the format string is inserted directly into the output.

YYYY
year (2001, 2002, ...)
YY
year (01, 02, ...)
Month
January, February, ...
MMM
Jan, Feb, ...
MM
number of the month (01, 02, ...)
Day
Monday, Tuesday, ...
DDD
Mon, Tue, ...
DD
day of the month
hh
hour (00, 01, ... 23)
mm
minute
ss
second

Because world.timeofday is in a range of 0 to 864000, values in this range are treated as a time for the current date. This way time2text() can return accurate results for world.timeofday. Any other values are interpreted as coming from world.realtime and will have the right time and date.


trimtext proc

See also:
copytext proc
Format:
trimtext(Text)
Returns:
Text with whitespace trimmed from both ends
Args:
Text: The text string to trim.

Trims whitespace from both ends of a text string.

All Unicode whitespace characters are counted, whether they can cause a break or not.


trunc proc

See also:
fract proc
floor proc
ceil proc
round proc
Format:
trunc(A)
Returns:
truncated A
Args:
A: A number.

Returns the integer part of the number A. That is, this rounds toward 0 to an integer.

Example:

usr << trunc(1.45) // outputs 1 usr << trunc(-1.45) // outputs -1

try and catch statements

See also:
Error proc (world)
throw statement
EXCEPTION proc
exception

The try and catch keywords are used for error handling. Any code that runs inside of a try block will, if an error happens or the throw keyword is used, stop executing and jump to the matching catch block. (This is also true of indirect proc calls. If you call a proc from inside a try block, any errors in that proc will be sent to the catch.)

For every try there must be a catch, even if it does nothing. The catch block takes an optional value that can receive the error.

Example:

var/a = 2 try a += "Hello" // will throw a type mismatch error catch(var/exception/e) // file and line info is available if you enable debugging world.log << "[e] on [e.file]:[e.line]" world << "a is [a]"

Because the value in the catch keyword is optional, you can simply use the catch keyword alone. It is also not necessary to include any code under the catch keyword, if the error is meant to be ignored. (However, it is not usually a good idea to ignore errors.)

The throw keyword is used if you want to throw an error deliberately. When you use throw, the error thrown does not have to be an /exception datum, but can be anything you like.


turn proc

See also:
Turn proc (icon)
dir var (atom)
Format:
turn(Dir, Angle)
Args:
Dir: One of NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST.
Angle: An angle in degrees (counterclockwise rotation).
Returns:
The rotated direction.

This proc can also be applied to an icon or a matrix.

Example:

var/dir dir = turn(NORTH, 90) // dir = west dir = turn(dir, -90) // dir = north dir = turn(dir, 45) // dir = northwest

Only multiples of 45 are allowed for angles. If an invalid angle is used, it will be treated as the closest multiple of 45 to 0.

If the supplied Dir is invalid, such as 0, or something like UP or DOWN, the result is a random direction unless the angle is also 0.


turn proc (applied to an icon)

See also:
turn proc
icon
Format:
turn(Icon, Angle)
Returns:
The rotated icon.
Args:
Icon: an icon to rotate
Angle: An angle in degrees (clockwise rotation).

Example:

mob/verb/drink() //this effect is very confusing! usr.icon = turn(usr.icon,90) usr << "Woah! That stuff is powerful!" sleep(200) usr.icon = turn(usr.icon,-90)

An icon that is not square will not be turned.

If the icon is an /icon datum, a new datum will be created as the result.


turn proc (applied to a matrix)

See also:
turn proc
matrix
Format:
turn(Matrix, Angle)
Returns:
A new matrix which has been rotated.
Args:
Matrix: a matrix to rotate
Angle: An angle in degrees (clockwise rotation).

Example:

mob/verb/drink() //this effect is very confusing! usr.transform = turn(usr.transform, 90) usr << "Woah! That stuff is powerful!" sleep(200) usr.transform = null

typesof proc

See also:
istype proc
locate proc
Format:
typesof(Type1,Type2,...)
Returns:
A list of all types that are derived from the specified "base" types, including the base types themselves.
Args:
The "base" types.

Example:

obj/fruit apple peach mango var/list/fruit_types = typesof(/obj/fruit)

In this example, fruit_types is initialized to contain /obj/fruit, /obj/fruit/apple, /obj/fruit/peach, and /obj/fruit/mango.

This procedure can also be used to list procs and verbs.

Example:

mob/admin_commands/verb shutdown_world() world.Del() reboot_world() world.Reboot() //for testing mob/verb/add_admin() verbs += typesof(/mob/admin_commands/verb) mob/verb/remove_admin() verbs -= typesof(/mob/admin_commands/verb)

uppertext proc

See also:
lowertext proc
Format:
uppertext(T)
Returns:
A capitalized text string.
Args:
T: A text string.

Capitalize all of the characters of T.

Example:

U = uppertext("hi there") // = "HI THERE"

url_decode proc

See also:
Topic proc (client)
url_encode proc
Format:
url_decode(UrlText)
Args:
UrlText: text to be "unescaped"
Returns:
unescaped text

Most non-alphanumeric characters are converted to another format in a URL. To send these characters literally, they must be "escaped".

The url_decode() instruction takes a text string containing such escaped symbols and turns them into their literal counterparts. Usually this is done for you automatically in Topic(). The more useful function is url_encode() which does the reverse.


url_encode proc

See also:
url_decode proc
Format:
url_encode(PlainText, format=0)
Args:
PlainText: text to be URL "escaped"
format: 0 to treat PlainText as a query string, 1 to treat it as a full URL
Returns:
escaped text

Special characters such as spaces are not used literally in URLs. If you want to ensure that an entire text string is sent literally, you can "escape" those characters. For example, a double quote (ASCII 34) is produced by the code %22, where 22 is hexadecimal for 34.

The url_encode() instruction does this for you automatically. Using format=1 will treat the URL as already encoded and only re-encode characters that don't belong in the result. Otherwise PlainText is treated as part of a query string; in this case spaces are converted to + instead of %20, and most characters are escaped.

Example:

mob/verb/Private(M as mob in players, T as text) if(!client || !M || !M.client || !T) return usr << "\[To <a href='?msg=[url_encode(M.key)]'>[M.name]</a>\] [T]" M << "\[From <a href='?msg=[url_encode(key)]'>[name]</a>\] [T]"

vars (procs)

See also:
procs

Built-in proc vars:

proc/var
.
args
src
usr

. var (proc)

See also:
return statement
vars (procs)

This is the default return value. If a proc exits without calling return or if no arguments are specified the value of . will be returned. The default value of . is null.

Example:

mob/Login() . = ..() view() << "[src] logs in."

args list var (proc)

See also:
list

This is a list of the arguments passed to the proc or verb.

Example:

proc/add() var {cur; tot} for(cur in args) tot += cur return tot

Here, add() may be called with any number of arguments, each accessed through the args list.


global var (proc)

See also:
src var (proc)

This is not really a variable but is used to force treatment of the following variable or proc as global. This may be necessary if a local or src-level variable has the same name.

Example:

var/myvar = "global" mob verb/test() var/myvar = "local" usr << myvar usr << global.myvar

This example outputs "local" and then "global".


src var (proc)

See also:
usr var (proc)
procs
verbs

This is a variable equal to the object containing the proc or verb. It is defined to have the same type as that object.

Example:

obj/bread verb/eat() world << "[usr] eats [src]"

If a player named "Bob" calls "eat bread", the output will be "Bob eats the bread."

Note that src has no meaning for global procs, derived from /proc, unless they are invoked as verbs (by being attached to a verb list).


usr var (proc)

See also:
src var (proc)
verbs
Topic proc (client)
range proc
view proc
alert proc
input proc

This is a mob variable (var/mob/usr) containing the mob of the player who executed the current verb, or whose action ultimately called the current proc.

Example:

obj/bread verb/eat() world << "[usr] eats [src]"

If a player named "Bob" calls "eat bread", the output will be "Bob eats the bread."

Essentially, usr is an implicit parameter that is passed to every proc or verb. Each procedure inherits the value from its caller. While it can simplify your code in some situations, it can also lead to subtle problems if you are assuming that usr is automatically assigned the value of src when you call a verb programmatically. It is not.

The only time usr is assigned for you is when a player executes a verb, clicks something with the mouse, clicks a link (see Topic), or any other such action.

Note: A good rule of thumb is to never put usr in a proc, only verbs. Typically usr in a proc is an unsafe programming practice. If src would not be the correct choice, it is better to send another argument to your proc with the information it needs.

Certain built-in procs such as atom/Click() are called automatically by a client counterpart like client/Click(); usually atom/Stat() is called by client/Stat(); and so on. It is mostly safe to apply usr as directed in those situations, because these procs are pseudo-verbs. It is mostly not safe to apply usr in a movement proc such as Move() or Enter(), because objs and non-player mobs may move autonomously without setting usr.

Although usr is often set in mob/Login() when a client first connects, you should not assume it is valid if Login() is called any other way. Common cases occur when creating a new character, loading a player's mob from a savefile; or explicitly when setting a mob's key or changing the value of client.mob. It is safest to use src in mob/Login(), which is always correct, rather than usr.

usr is the default point of reference for several procs like view() and range(), because of their common use in verbs. It is also the default recipient for input() and alert() messages. When using these in procs, be aware of that so you can change the default reference value to something more appropriate.


view proc

See also:
<< output operator
hearers
oview proc
range proc
see_in_dark var (mob)
see_infrared var (mob)
see_invisible var (mob)
sight var (mob)
view var (client)
view var (world)
viewers
Format:
view(Dist=5,Center=usr)
Returns:
A list of visible objects within Dist tiles of Center.
Args:
Dist: A number.
Center: An object on the map.

A Dist of 0 includes Center, the contents of Center (normally usr.contents), its location (normally the turf a mob is standing on), and any other contents of that location. A value of 1 extends the region to the neighboring squares on the map and so on. Both arguments are optional and may be passed in any order.

The default range is actually controlled by the size of the map viewport size, which is configured with world.view. Since the default value of that variable is 5, the default range is also 5. You may use any valid view size, so an explicit view size such as "11x17" is also valid.

Example:

view() << "to all in sight of [usr]" view(src) << "to all in sight of [src]" view(1,src.loc) << "to all within reach of [src]"

Be aware of the following distinctions:

view(usr) //objects that usr can see view(usr.loc) //objects visible from usr's position view(usr.client) //objects visible to player

In many cases, the three different statements could produce the same result, but they are not identical in general. For example, the first statement takes into account the visual capabilities of usr, which might include such things as the ability to see in the dark or to see invisible objects.

The second statement, since it is from a non-mob would just do a plain visibility calculation with no special visual capabilities. In many cases, you would want to use viewers() or hearers() instead.

The third statement produces a list of visible objects as the player sees things, which might be different than how the mob sees things if client.eye and client.mob are different.


viewers

See also:
hearers
oviewers
view proc
Format:
viewers(Depth=world.view,Center=usr)

This is just like view(), but it is a list of mobs that can see the center object, rather than a list of objects visible to the center object.


walk proc

See also:
get_step proc
step proc
step_size var (movable atom)
Format:
walk(Ref,Dir,Lag=0,Speed=0)
Args:
Ref: A mob or obj.
Dir: One of NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST, or 0 to halt.
Lag: Delay in world ticks between movement.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref in the direction Dir continuously. Each step will be preceded by Lag time of inactivity.

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.


walk_away proc

See also:
get_step_away proc
step_away proc
step_size var (movable atom)
Format:
walk_away(Ref,Trg,Max=5,Lag=0,Speed=0)
Args:
Ref: A mob or obj.
Trg: An object on the map.
Max: The maximum distance between Ref and Targ before movement halts.
Lag: Delay in world ticks between movement.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Moves Ref on a path away from Trg continuously, taking obstacles into account. Each step will be preceded by Lag time of inactivity. If Ref is farther than Max steps from Trg, no action will be taken.

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.


walk_rand proc

See also:
get_step_rand proc
step_rand proc
step_size var (movable atom)
Format:
walk_rand(Ref,Lag=0,Speed=0)
Args:
Ref: A mob or obj.
Lag: Delay in world ticks between movement.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Moves Ref randomly. Each step will be preceded by Lag time of inactivity.

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.


walk_to proc

See also:
get_step_to proc
step_to proc
step_size var (movable atom)
Format:
walk_to(Ref,Trg,Min=0,Lag=0,Speed=0)
Args:
Ref: A mob or obj.
Trg: An object on the map.
Min: The minimum distance between Ref and Trg before movement halts.
Lag: Delay in world ticks between movement.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref on a path to Trg continuously, taking obstacles into account. Each step will be preceded by Lag time of inactivity. If Ref is within Min steps of Trg, no action will be taken. This is also true if the target is too far away (more than twice world.view steps).

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.


walk_towards proc

See also:
get_step_towards proc
step_towards proc
step_size var (movable atom)
Format:
walk_towards(Ref,Trg,Lag=0,Speed=0)
Args:
Ref: A mob or obj.
Trg: An object on the map.
Lag: Delay in world ticks between movement.
Speed: Speed to move, in pixels. 0 uses Ref.step_size.

Move Ref in the direction of Trg continuously. Each step will be preceded by Lag time of inactivity.

A call to a walking function aborts any previous walking function called on Ref. To halt walking, call walk(Ref,0).

This function returns immediately, but continues to process in the background.


while proc

See also:
break statement
continue statement
do proc
for loop proc
Format:
while(E) Statement

If E is true (non-zero) execute Statement. Continue testing E and doing the while block until E becomes false (zero).

Statement may be a block of code or a single statement.

Example:

var/i = 3 while(i) world << i--

This outputs:

3 2 1

winclone proc

See also:
winexists proc
winget proc
winset proc
winshow proc
User interface skins
Format:
winclone(player, window_name, clone_name)
Args:
player: A mob or client.
window_name: The name of a window, pane, menu, or macro set in the world's skin file.
clone_name: The name of the new window, pane, menu, or macro set to create.

Creates a clone of a window, pane, menu, or macro set that exists in the world's skin file. The original object as it exists in the skin file (not its current state) is used as a template to build the clone. The clone will exist only for the player you choose.

Example:

winset(usr, "templatewindow", "clonedwindow")

If a window is not visible by default, it will have to be shown with winset() or winshow(). A pane may be shown by using it in a Child or Tab control. Menus or macros must be assigned to a window with winset() before they will work.

If window_name is "window", "pane", "menu", or "macro", and the skin file does not have a control of that name already, the proc will create a new control of that type from scratch.

Example:

winclone(usr, "menu", "newmenu") winset(usr, "newmenu_file", "parent=newmenu;name=File") winset(usr, "newmenu_quit", "parent=newmenu_file;name=Quit;command=.quit")

A new window is invisible by default. For windows and panes, you should give them a size with winset() before adding any controls so you can set their anchors properly.

Example:

// Create the pane winclone(usr, "pane", "newpane") // Give it a size so we can figure out where to put controls winset(usr, "newpane", "size=100x100") // Add controls winset(usr, "newpane_label", \ "parent=newpane;pos=0,0;size=100x100;anchor1=0,0;anchor2=100,100") // Put the pane in a child control where it can be seen winset(usr, "a_child", "left=newpane") usr << output("New label", "newpane_label")

Once a clone is created, it can be deleted via a winset() call:

Example:

winset(usr, "clonedwindow", "parent=none")

winexists proc

See also:
winclone proc
winget proc
winset proc
winshow proc
User interface skins
type parameter (skin)
Format:
winexists(player, control_id)
Args:
player: A mob or client.
control_id: The unique ID of a control in the player's skin.

Tells if a control exists and if so, what type it is. The return value is an empty string if the control does not exist, but otherwise it is the type of control.

This proc will not tell you if a control has been defined in the skin file but is not in use yet.

Because the client must be contacted to get this information, winexists() will sleep the current proc.


winget proc

See also:
winexists proc
winset proc
User interface skins
parameters (skin)
Format:
winget(player, control_id, params)
Args:
player: A mob or client.
control_id: The unique ID of a control in the player's skin.
params: The name of a parameter to read, or a semicolon-separated list of parameters

Retrieves info from a player about the current state of their skin. If control_id and params are each just a single value, then the return value will be a simple string with the value of that parameter. If control_id or params is a semicolon-separated list like the kind used in list2params(), then the result will be in a similar format, and can be converted to a list form using params2list().

The control_id can be a window name, or in a "[window].[control]" format, or just the control's ID itself as long as it is unique. Another valid form is ":[type]" which selects the default control of that type, e.g. ":map" for the main map. As mentioned above, you can retrieve info on more than one control at once by separating them with semicolons, like "button1;button2".

Example:

usr << "mainwindow.is-visible = [winget(usr, "mainwindow", "is-visible")]" usr << "\nOther params:" usr << winget(usr, "mainwindow", "pos;is-maximized") usr << "\nButtons:" usr << winget(usr, "button1;button2", "is-checked")

This outputs:

mainwindow.is-visible = true Other params: pos=0x0;is-maximized=true Buttons: button1.is-checked=true;button2.is-checked=false

If the returned result is actual text for any parameters, the single quote or double quote characters may be escaped with a backslash. An actual backslash will also be escaped with a backslash.

You can also use a special wildcard format to retrieve info about all the controls in a window, menu, or macro set. If control_id is "mainwindow.*" for instance, then any control that is part of mainwindow—and mainwindow itself—is included in the result if it has the parameter(s) you're looking for. Use params2list() to interpret the result.

Note: Because the client must be contacted to get this information, winget() will sleep the current proc.

Special wingets

Calling winget() with a blank or null control_id can return some values that belong to the client as a whole, not to specific controls. They can also be used for embedded wingets.

focus
The full ID of the control, if any, that currently has keyboard focus.
windows
The IDs of all windows, separated by semicolons.
panes
The IDs of all panes, separated by semicolons.
menus
The IDs of all menus, separated by semicolons.
macros
The IDs of all macro sets, separated by semicolons.
sound
True if sounds are enabled.
hwmode
True if the map displays in hardware rendering mode.
url
The URL the client is connected to in IP:port form. The port is 0 if connected to a local .dmb file, and either an empty string or null is returned if Dream Seeker is not connected at all.
num-lock
True if Num Lock is on.
caps-lock
True if Caps Lock is on.
scroll-lock
True if Scroll Lock is on.

winset proc

See also:
winclone proc
winexists proc
winget proc
winshow proc
User interface skins
parameters (skin)
Format:
winset(player, control_id, params)
Args:
player: A mob or client.
control_id: The unique ID of a control in the player's skin.
params: A text string with parameters to set, in the format returned by list2params(); OR an associative list.

Sets parameters for a player's skin. The parameter list can be created by making a list and using list2params(), or it can be done manually by just using a string like "is-visible=true;text-color=#f00". You can also just use a list directly, which will be passed to list2params() internally.

The control_id can be a window name, or in a "[window].[control]" format, or just the control ID as long as it is unique. In some special cases it can also be null. Another valid form is ":[type]" which selects the default control of that type, e.g. ":map" for the main map.

If you want to use a text string that may include spaces, surround the string with double quotes and escape them using a backslash, e.g. "text=\"This is some text.\"". Backslashes can also be used by preceding them with another backslash. For filenames, use single quotes around the file. Sometimes escapement may need to go several levels deep; for example to set up an input control with a default say command, you will need to escape it twice:

Desired command: say "
Escaped form with quotes: "say \""
Final form: \"say \\\"\"

winset(usr, "mainwindow.input", "command=\"say \\\"\"")

You can set more than one control's parameters at once by leaving the control_id argument null, and including the control as part of the parameter list:

winset(usr, null,\ "mainwindow.output.background-color=#ffffff;mainwindow.input.background-color=#ffffff")

Special winsets

Some "global" winset options will let you change things that affect the client as a whole, not just specific controls.

You can reset the skin to its beginning state, removing all runtime-created controls and windows, by calling winset(player, null, "reset=true").

Another use for winset() is to send commands to the client that normally can only run from there, like .profile or .quit. To do this, leave the control_id argument null, and just use a parameter called "command":

obj/quitbutton name = "Quit" icon = 'buttons.dmi' icon_state = "quit" Click() winset(usr, null, "command=.quit")

winshow proc

See also:
winclone proc
winget proc
winset proc
User interface skins
is-visible parameter (skin)
Format:
winshow(player, window, show=1)
Args:
player: A mob or client.
window: The name of a window in the player's skin.
show: Use a nonzero value to show the window, zero to hide it.

Shows or hides a window in the player's skin. This is a shortcut, equivalent to setting is-visible via winset().


regex datum

See also:
Regular expressions
regex procs
regex vars
regex proc
REGEX_QUOTE proc
findtext proc
splittext proc
stddef.dm file

The /regex datum holds a regular expression that can be used for searching and/or replacing text. Rather than searching for a specific piece of text, a regular expression is a pattern to search for. This can include things like wildcards. See Regular expressions for more information.

A new regular expression can be created with regex() or new/regex().


regex procs

See also:
regex datum
regex vars
regex proc
regex/proc
New
Find
Replace

Find proc (regex)

See also:
Regular expressions
regex datum
Replace proc (regex)
regex vars
regex proc
findtext proc
Format:
Find(haystack, Start=1, End=0)
Returns:
The position of the matched text, or 0 if no match was found.
Args:
haystack: The text to be searched
Start: The start position (in bytes) to search; defaults to 1, or to src.next if this is a global pattern
End: The position of the byte after the end of the search; 0 is the end. The actual match is allowed to extend past End.

Finds the regular expression pattern within the "haystack" text. The following vars are set by the match:

In a global expression (using the "g" flag), Find() can be called repeatedly on the same piece of text and the Start position will be advanced automatically unless you specify it.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use Find_char() to work with character counts instead of bytes, at a performance cost. See the Unicode section for more information.


New proc (regex)

See also:
Regular expressions
regex datum
regex proc
Format:
regex(pattern, flags)
regex(Regex)
Args:
pattern: The pattern string to search for
flags: (optional) A text string containing any combination of modifier flags
Regex: an existing /regex datum to copy

Calling new/regex() is the same as calling regex(). It will create a new /regex datum.


Replace proc (regex)

See also:
Regular expressions
regex datum
Find proc (regex)
regex vars
regex proc
replacetext proc
Format:
Replace(haystack, replacement, Start=1, End=0)
Returns:
The original haystack string with the first match replaced. If using the "g" flag, all matches are replaced.
Args:
haystack: The text to be searched
replacement: A piece of text, OR a proc, that will be used to replace the match
Start: The start position (in bytes) to search; defaults to 1, or to src.next if this is a global pattern
End: The position of the byte after the end of the search; 0 is the end. The actual match is allowed to extend past End.

Finds the regular expression pattern within the "haystack" text, and replaces the match with the given replacement value.

In a non-global expression (not using the "g" flag), the values of src.index and src.next are set as they would be in a global Find(). See the Find() proc for more info.

Note: In strings containing non-ASCII characters, byte position and character position are not the same thing. Use Replace_char() to work with character counts instead of bytes. See the Unicode section for more information.

Replacing with text

If the replacement value is text, the $ character is treated as special. If you want to use the actual dollar sign, it must be escaped with a second dollar sign. Otherwise, the $ character is one of these special values:

ReplacementValue
$1 through $9$1tt> is whatever was in the first parentheses group, $2 is the second, and so on.
$`The text that came before the match
$'The text that came after the match
$0 or $&The whole match itself

Replacing with a proc

If replacing matches with a proc, then the proc will be called with the match as its first argument, and any capturing groups as the following arguments. Whatever the proc returns will be used as the replacement text in place of the match.

Example

var/regex/vowels = new("[aeiou]", "i") // match any word of 2 letters or more var/regex/piglatin = new("\\b(\\l)(\\l+)\\b", "ig") // group1 is the first letter, and group2 is everything else proc/word2piglatin(match, group1, group2) // If the word starts with a vowel, just add "ay" if(vowels.Find(group1)) return "[match]ay" // If the word was capitalized, capitalize the replacement if(group1 == uppertext(group1)) group1 = lowertext(group1) group2 = uppertext(copytext(group2,1,2)) + lowertext(copytext(group2,2)) return "[group2][group1]ay" mob/verb/PigSay(msg as text) msg = html_encode(msg) world << piglatin.Replace(msg, /proc/word2piglatin)

regex vars

See also:
regex datum
regex procs
regex proc
regex/var
flags
group
index
match
name
next
text

flags var (regex)

See also:
Regular expressions
regex datum
name var (regex)

The flags that were used to create this regular expression. Changing this value after the datum is created will not change how the expression behaves.


group var (regex)

See also:
regex datum
Find proc (regex)
index var (regex)
match var (regex)

After a call to Find(), if this regular expression had any parentheses groups, whatever text was matched in those groups is stored here in a list.

Example

var/regex/R = new("B(.)(.)(.)D") R.Find("BYOND") // find this pattern in "BYOND" The result of the example is that R.group is list("Y","O","N").

index var (regex)

See also:
regex datum
Find proc (regex)
Replace proc (regex)
match var (regex)
next var (regex)

After a call to Find(), this var contains the index where the match was found.

Replace() on a non-global pattern will also store the index of the match here.


match var (regex)

See also:
regex datum
Find proc (regex)
group var (regex)
index var (regex)

After a call to Find(), this var contains the text that was matched.


name var (regex)

See also:
regex datum
flags var (regex)

The pattern that was used to create this regular expression. Changing this value after the datum is created will not change how the expression behaves.


next var (regex)

See also:
regex datum
Find proc (regex)
Replace proc (regex)
index var (regex)
match var (regex)

If this is a global pattern (using the "g" flag), then after a call to Find() this var contains the index where next Find() should begin.

Replace() on a non-global pattern will also store the index of the next place to begin a search here. The position to search will be based on the replaced text, which is stored in the text var.


text var (regex)

See also:
regex datum
Find proc (regex)
index var (regex)
match var (regex)
next var (regex)

If this is a global pattern (using the "g" flag), then after a call to Find() this var contains the text that was searched. If that same text is searched again, the next var is the default starting position.

Replace() on a non-global pattern will store the text after replacement here.


savefile

See also:
>> operator (savefile)
<< operator (savefile)
Export proc (client)
New proc (client)
procs (savefile)
vars (savefile)
tmp vars
issaved proc
Read proc (datum)
Write proc (datum)

A database file in DM is called a "savefile". All of the contents of a savefile reside in a single file. The contents of the file are stored in database directories. These should not be confused with real directories in the external file system. The database directories are all contained inside the one file.

Each database directory contains a list of sub-directories and a buffer in which data may be written. The absolute path to a directory has the following format: "/Dir1/Dir2/...". The current directory may be set by assigning its absolute path name to savefile.cd. A relative path (one that doesn't begin with "/") may also be used, in which case the new path starts at the current directory. The path "." stands for the current directory, ".." for its parent, "../.." for its parent's parent, etc.

A savefile may be created with new/savefile(name). The optional name argument may be an external file name (existing or to be created) in double quotes or a file from the resource cache in single quotes. Of course, a variable containing either of these types of values may also be used. If no name is specified, a temporary file will be created, which will be destroyed when the savefile is no longer in use. If a resource cache is specified, a temporary file will be created and the contents of the cached file will be copied into it. Changes will therefore only be temporary.


operators (savefile)

Built-in savefile operators:

savefile/operator
<<
>>

>> operator (savefile)

See also:
>> input operator
<< operator (savefile)
Read proc (datum)
Format:
F >> Var
F["Path"] >> Var

Reads a value from a buffer into a variable. If Path is not specified, the current buffer will be used. Otherwise, the buffer at the specified path will be accessed. Whenever the current directory is set, reading starts at the beginning of that buffer (replacing any previous contents). For this reason, when the Path parameter is given, the first value in the specified buffer is always read. If there is no data in the buffer or the end of the buffer has been reached, null is returned.

If the value read is a previously written object, its own directory will be opened and the object's Read proc will be called to load any data that was written in the object's Write proc.

If the value read is a savefile (ie a savefile inside of a savefile), it is treated a little differently. Instead of returning a savefile object, it returns data cached in the world's rsc file. This is to give you control over what file this data is copied into before it is opened as a savefile. If you want to just open it up in a temporary file, do something like this:

obj var savefile/myfile Read() . = ..() //do the normal stuff if(myfile) //load data into a temporary file and create savefile object myfile = new/savefile(myfile)

<< operator (savefile)

See also:
>> operator (savefile)
<< output operator
Write proc (datum)
Format:
F << Val
F["Path"] << Val

Writes Val to a buffer. If Path is not specified, the current buffer will be used. Otherwise, the buffer at the specified path will be written to. Whenever the current directory is set, writing starts at the beginning of that buffer (replacing any previous contents). For this reason, when the Path parameter is given, the specified buffer is always overwritten.

If Val is an object, a separate directory will be created for the object and the object's Write proc will be called. In addition to data that may be written by the Write() proc, the type of the object is stored in a buffer called "type". In the case of turfs, the location of the turf is also recorded so that it can be recreated at the same position. All other objects must be repositioned after the object is recreated (like in the object's Read() proc).

Single operations that write multiple values (such as saving an object) are handled somewhat specially to avoid two references to the same object creating duplicate entries in the savefile. After the object being referenced is written once, successive references to the same object will be saved simply as references rather than as full objects. If this was not done, two references to the same object would be read back in as two separate objects. This also avoids infinite loops that would result when objects contain references back to themselves.


procs (savefile)

savefile/proc
ExportText
Flush
ImportText
Lock
Unlock
New

ExportText proc (savefile)

See also:
ImportText proc (savefile)
Format:
savefile.ExportText(path=cd,file)
Args:
path: the path to export
file: optional file to write to

Converts all or part of a savefile to a human readable text format, similar in syntax to DM. If no file is specified, the savefile text is returned as a text string instead of being written to a file.

The following example shows how to export and later import a savefile. The user's mob is written into a directory with the same name as their ckey and the result is written to a text file.

Example:

mob/verb/write() var/savefile/F = new() var/txtfile = file("players/[ckey].txt") F[ckey] << usr fdel(txtfile) F.ExportText("/",txtfile) usr << "Your savefile looks like this:" usr << "<pre>[html_encode(file2text(txtfile))]</pre>" mob/verb/read() var/savefile/F = new() var/txtfile = file("players/[ckey].txt") F.ImportText("/",txtfile) F[ckey] >> usr

Flush proc (savefile)

Format:
savefile.Flush()

Flushes any pending write operations for this savefile.


ImportText proc (savefile)

See also:
ExportText proc (savefile)
Format:
savefile.ImportText(path=cd,source)
Args:
path: the path at which to write the imported data
source: a file or text string to import

Reads a text file or string and writes it into a savefile. See ExportText for an example.

If source is an ordinary string, it will be treated as savefile contents to be parsed. If it's a file() reference, it will be treated as a filename and the file's contents will be loaded.


Lock proc (savefile)

See also:
New proc (savefile)
Unlock proc (savefile)
Format:
Lock(timeout)
Args:
timeout: seconds to wait; -1 for no timeout
Returns:
1 on success; 0 on failure

In order to modify a savefile, exclusive access to the file must be guaranteed, so that other processes reading or writing to the file do not experience data corruption. This is known as "locking" the file. While the file is locked, only the world that obtained the lock may access it.

Normally, you do not need to worry about this, because a lock is automatically obtained upon the first attempt to write to the file. In a CGI application, where many instances of the program might be running simultaneously, the normal locking, which just tries once and crashes the proc on failure, would not be ideal.

Explicitly calling Lock() allows you to specify a timeout and it also allows you to handle the case in which no lock could be obtained. If you want it to wait indefinitely, use -1. Just be careful if there are several files read by multiple processes that it is not possible for deadlock to occur.

Obtaining a lock will fail if the file is locked by another world or if it is even open by any other world.

If you are using Lock(), then you probably also want to specify a timeout when you open the savefile, since that too can fail due to the file being locked by another process.


New proc (savefile)

See also:
Lock proc (savefile)
Unlock proc (savefile)
Format:
New(filename,timeout)
Args:
filename: name of file or empty for temporary file
timeout: seconds to wait; -1 for no timeout

You call this via new/savefile(filename,timeout). The timeout is used to determine how long to wait if the file is locked. Normally (timeout=0), if the file is locked, the proc crashes with a runtime error. If you specify a timeout, then it will keep trying to open the file and if this fails, it will simply return with savefile.name being empty (ie a false value).

If the first argument is an entry in the world's rsc cache, the data will be copied into a temporary file and accessed from there. Changes to this, and any other temporary file, are not saved. When you close the file, it simply gets deleted.


Unlock proc (savefile)

See also:
Lock proc (savefile)
New proc (savefile)
Format:
Unlock()

Exclusive locks are automatically released when the savefile is closed, but if you want to keep reading the file and allow other processes to do the same, then you can explicitly unlock it.

Note that this does not allow other processes to lock the file. It only allows them to read from it. As long as the file is open by more than one process, no lock may be obtained.


vars (savefile)

savefile vars:

savefile/var
byond_build
byond_version
cd
dir
eof
name

byond_build var (savefile)

See also:
savefile
byond_version var (savefile)
byond_version var (world)
byond_build var (world)
Default value:
0

Sometimes when transitioning between BYOND versions you'll want to keep a savefile in a condition where it can be read by older versions. The byond_version var tells it to avoid using newer savefile features (unless forced to) above a certain build number. (The build number changes more often than the BYOND version number.) A value of 0 means not to worry about it.

This can be changed on a per-savefile basis so that you can use newer features in some files and avoid changing others. For instance, character saves might want to go on using older features for a while, but for saving parts of the map you might prefer to allow newer features to be used.

The default savefile compatibility version can be set at compile-time:

Example:

savefile/byond_build = 1600 // do not use savefile features from BYOND build 1601 onward

byond_version var (savefile)

See also:
savefile
byond_build var (savefile)
byond_version var (world)
byond_build var (world)
Default value:
0

Sometimes when transitioning between BYOND versions you'll want to keep a savefile in a condition where it can be read by older versions. The byond_version var tells it to avoid using newer savefile features (unless forced to) above a certain version number. A value of 0 means not to worry about it.

This can be changed on a per-savefile basis so that you can use newer features in some files and avoid changing others. For instance, character saves might want to go on using older features for a while, but for saving parts of the map you might prefer to allow newer features to be used.

The default savefile compatibility version can be set at compile-time:

Example:

savefile/byond_version = 514 // do not use savefile features from BYOND 515 onward

Note: By default, worlds compiled before BYOND 515 will set this value to 514.


cd var (savefile)

See also:
savefile

This is the path name of the current directory. Setting it causes the current directory to change. (We are talking about the current database directory inside the savefile. It is not a real directory on the filesystem.) It is perfectly legal to change to a non-existent directory. This new directory will not be saved to disk unless its buffer (or one of its children) is modified, however.

Example:

var/savefile/F = new() // temporary file F.cd = "/MyDir/Icon" F.cd = ".." // change to /MyDir F.cd = "Icon" // change to /MyDir/Icon

dir list var (savefile)

See also:
list
savefile

The name of each child directory of the current data directory is stored in the list savefile.dir. New directories may be created with savefile.dir.Add() and removed with savefile.dir.Remove(). To test for the existence of a directory, use savefile.dir.Find(). (Note that these are database directories inside the savefile—not real directories on the filesystem.)

The order of directories is not necessarily preserved, so do not assume, for example, that newer directories will be at the end of the list.


eof var (savefile)

If there is more data to read in the current buffer, eof is 0; otherwise it is 1. Setting eof to 1 moves to the end of the buffer and 0 moves to the beginning. Setting it to -1 deletes the current buffer.


name var (savefile)

See also:
savefile

The external "real" filename is stored in file.name. It is initialized when creating a new file. If none is specified, a temporary file with a random name will be created.

Example:

var/savefile/F1 var/savefile/F2 F1 = new() // create a temp file F2 = new("myfile") // open "myfile" world << "F1.name = [F1]" world << "F2.name = [F2]"

sound datum

See also:
vars (sound)
sound proc
stddef.dm file
load_resource proc

A /sound datum is created by the sound() proc or by new/sound(). It can be used to change the way a sound file will play. When you're ready to play the sound, just send it to a player like so:

var/sound/S = sound('bubbles.wav') usr << S

The sound file can be supplied as a list of choices, in which case the client will play the first compatible sound in the list.


vars (sound)

Built-in sound vars:

sound/var
file
repeat
wait
channel
volume
frequency
len
offset
pan
params
pitch
priority
status
x, y, z
falloff
environment
echo

file var (sound)

See also:
sound proc
vars (sound)
SoundQuery proc (client)

This is the file that will be played when the sound is sent to a player.

If this value is a list of files rather than a single file, the client will play the first compatible sound in the list. This can be useful for developing webclient games, where .ogg is preferred by most browsers for audio, but .mp3 is needed for others.

This var may be filled in by the SoundQuery proc.


repeat var (sound)

See also:
sound proc
vars (sound)
SoundQuery proc (client)
Default value:
0 (do not repeat)

Set to 1 to repeat the sound indefinitely once it begins playing, 2 to repeat it forwards and backwards.

This var may be filled in by the SoundQuery proc.


wait var (sound)

See also:
sound proc
vars (sound)
SoundQuery proc (client)
Default value:
0 (do not wait)

Set to 1 to wait for other sounds in this channel to finish before playing this one.

The SoundQuery proc fills in this value with the total duration of sounds that are queued to be played on this channel.


channel var (sound)

See also:
sound proc
status var (sound)
vars (sound)
SoundQuery proc (client)
Default value:
0 (any channel)

For sound effects, set to 1 through 1024 to choose a specific sound channel. For values of 0 or less, any available channel will be chosen. If you play a null sound (no file) on channel 0, the settings for the datum will affect all channels.

If you want to make any changes to your sound later on via the SOUND_UPDATE status flag, you must specify a channel for it.

This var may be filled in by the SoundQuery proc, but only for sounds that had a specified channel to begin with.

Note: If you don't specify a channel to play a sound, the client will choose a channel automatically but it will not conflict with any specific channels you choose for other sounds later. This means if you play some sounds with channel 0 but then later want to play something on channel 1, you don't have to worry about channel 1 being taken.


volume var (sound)

See also:
sound proc
vars (sound)
Default value:
100 (full volume)

Set to a percentage from 0 to 100 of the sound's full volume. It will play at that volume when it is sent to a player.


frequency var (sound)

See also:
vars (sound)
pitch var (sound)
Default value:
0

Any value from -100 to 100 will play this sound at a multiple of its normal frequency. Set to 2 to play at double speed, for example, or -1 to play backwards. A value of 0 or 1 will play the sound at its normal frequency.

Set to a specific frequency (in Hz) outside of the -100 to 100 range to change the playback rate of the sound. A negative value is also allowed. The value 0 means that the sound should be played as-is. This value will take effect when the sound is sent to a player.

CD-quality sound is sampled at 44.1 KHz, which is a value of 44100. Other common sample rates for .wav files are 8000, 11025, and 22050. (11025 is usually a good quality for most sound effects without making file size too large.) If you know the file's sample rate, doubling the value will play it at a higher pitch and twice as fast; halving it will play it at a lower pitch and twice as slow.

To make a sound play at a different speed but keep its pitch intact, set frequency to the speed multiple you want (e.g., 1.2 for 20% faster) and set pitch to the inverse (e.g., 1/1.2).


offset var (sound)

See also:
vars (sound)
status var (sound)
SoundQuery proc (client)

Can be used to set a starting time, in seconds, for a sound. It can also alter the current time index when using the SOUND_UPDATE flag.

This value is also set by the SoundQuery proc and represents the current time index of a sound playing on the client.


len var (sound)

See also:
vars (sound)
SoundQuery proc (client)

This value is set by the SoundQuery proc and represents the length, in seconds, of a sound playing on the client. Frequency is taken into into consideration, so a higher frequency means the sound takes a shorter time to play and therefore has a shorter length.

Other uses for this var may be considered in the future.


pan var (sound)

See also:
vars (sound)
Default value:
0

Alter the panning of a sound. -100 is full left, 100 is full right, and 0 is at the center. This value will take effect when the sound is sent to a player.

For music, pan can range from -100 (no pan separation) to 0 (full separation).


params var (sound)

See also:
vars (sound)
Default value:
null

Used to set client skin information related to this sound. This can be set to an associative list or a parameter string such as you would get from list2params().

The only parameter currently defined is on-end, which is a command the client will run when the sound ends.

Example:

mob/proc/PlayIntro() var/sound/S = sound('intro.ogg') S.params = list("on-end" = ".intro-ended") src << S mob/verb/_Intro_Ended() set name = ".intro-ended" src << "The intro has concluded."

pitch var (sound)

See also:
vars (sound)
frequency var (sound)
Default value:
0

Can be used to shift the pitch of a sound up or down. This works similarly to frequency except that it doesn't impact playback speed.

The value of this var should be a multiple relative to 1, so for instance to go up a full octave, the value would be 2; to go down an octave, use 0.5.

Note: The filter that handles pitch shifting only goes from 0.5 to 2. The player will stack up to three filters if it has to, so the range is really from 0.125 to 8. You will however hear much poorer quality at more extreme values.

To make a sound play at a different speed but keep its pitch intact, set frequency to the speed multiple you want (e.g., 1.2 for 20% faster) and set pitch to the inverse (e.g., 1/1.2).

Example:

client var/sound/music // music currently playing proc/PlayMusic(music) music = new(music) music.channel = 100 src << music proc/UpTempo(amount = 0.1) // 10% faster if(!music) return music.frequency = (music.frequency || 1) + amount music.pitch = 1 / music.frequency music.status |= SOUND_UPDATE src << music

priority var (sound)

See also:
vars (sound)
Default value:
0

Sounds with higher priority may steal channels from sounds of lower priority. The maximum value is 255. 0 is the lowest.


status var (sound)

See also:
vars (sound)
SoundQuery proc (client)
Default value:
0

Alter the way the sound is heard by affecting several different on/off values which combine as bit flags.

SOUND_MUTE // do not play the sound SOUND_PAUSED // pause sound SOUND_STREAM // create as a stream SOUND_UPDATE // update a playing sound

Use the | operator to combine these values. The setting you choose will take effect when the sound is sent to a player.

SOUND_MUTE | SOUND_UPDATE will mute a sound, but it will continue to play. It can be unmuted while still playing by resending it with status=SOUND_UPDATE.

SOUND_PAUSED | SOUND_UPDATE will pause a sound. It can be restarted from its current position by resending it with status=SOUND_UPDATE.

SOUND_STREAM will create this sound as a stream. Streams take less memory, but can not play multiple times at once, nor can they play in reverse. This flag is only valid the first time that a sound is played in a particular mode (normal vs. 3D). Changing the flag later will not change the stream status of the sound in that mode.

SOUND_UPDATE updates the settings for the sound currently playing on the specified channel. If this flag is not set or no channel is specified, the sound will start again from the beginning.

Some of the flags for this value may be filled in by the SoundQuery proc.


x, y, and z vars (sound)

See also:
vars (sound)
falloff var (sound)
Default value:
all 0

Set to different values to give your sound a 3D effect which will be applied when it is played. Positive values for x will sound as if they come from the right, positive y sounds like it is above the player's head, and positive z sounds like it is directly ahead. The effect of 3D sound depends on the player's computer's sound card, and is greatly enhanced when wearing headphones.

Depending on the value of falloff, the settings for the location of the sound can also affect its volume. Once the distance passes the value of falloff, the volume will diminish.

If these values are all set to 0, you should set environment if you want to treat it as a 3D sound. Otherwise BYOND will assume this is meant to be a non-3D sound such as music or the interface.


falloff var (sound)

See also:
vars (sound)
x, y, z vars (sound)
Default value:
1

Within the falloff distance a 3D sound stays at the constant loudest volume possible. Outside of this distance it attenuates at a rate determined by the falloff.

Higher values will make sounds fade out more slowly as they get farther away. The distance of a sound is set by x, y, and z.


environment var (sound)

See also:
vars (sound)
x, y, z vars (sound)
echo var (sound)
Default value:
-1

Changes the environmental reverb for all 3D sounds until another environment is specified. Only 3D sounds react to the environment. Please see the EAX2 documentation at http://developer.creative.com/ for detailed information about these settings.

This value may be a number which selects a preset, or a list to choose settings manually. The default value (-1) specifies no change in environment. A numeric value from 0 to 25 specifies a set of reverb presets for the environment. The environment presets are:

  1. generic
  2. padded cell
  3. room
  4. bathroom
  5. livingroom
  6. stoneroom
  7. auditorium
  8. concert hall
  9. cave
  10. arena
  11. hangar
  12. carpeted hallway
  13. hallway
  14. stone corridor
  15. alley
  16. forest
  17. city
  18. mountains
  19. quarry
  20. plain
  21. parking lot
  22. sewer pipe
  23. underwater
  24. drugged
  25. dizzy
  26. psychotic

As of BYOND 515, setting environment to a negative number below -1 will turn the environment off. The generic environment is not the same as off.

A 23-element list represents a custom environment with the following reverbration settings. A null or non-numeric value for any setting will select its default.

1 EnvSize (1.0 to 100.0) default = 7.5
environment size in meters
2 EnvDiffusion (0.0 to 1.0) default = 1.0
environment diffusion
3 Room (-10000 to 0) default = -1000
room effect level (at mid frequencies)
4 RoomHF (-10000 to 0) default = -100
relative room effect level at high frequencies
5 RoomLF (-10000 to 0) default = 0
relative room effect level at low frequencies
6 DecayTime (0.1 to 20.0) default = 1.49
reverberation decay time at mid frequencies
7 DecayHFRatio (0.1 to 2.0) default = 0.83
high-frequency to mid-frequency decay time ratio
8 DecayLFRatio (0.1 to 2.0) default = 1.0
low-frequency to mid-frequency decay time ratio
9 Reflections (-10000 to 1000) default = -2602
early reflections level relative to room effect
10 ReflectionsDelay (0.0 to 0.3) default = 0.007
initial reflection delay time
11 Reverb (-10000 to 2000) default = 200
late reverberation level relative to room effect
12 ReverbDelay (0.0 to 0.1) default = 0.011
late reverberation delay time relative to initial reflection
13 EchoTime (0.075 to 0.250) default = 0.25
echo time
14 EchoDepth (0.0 to 1.0) default = 0.0
echo depth
15 ModulationTime (0.04 to 4.0) default = 0.25
modulation time
16 ModulationDepth (0.0 to 1.0) default = 0.0
modulation depth
17 AirAbsorptionHF (-100 to 0.0) default = -5.0
change in level per meter at high frequencies
18 HFReference (1000.0 to 20000) default = 5000.0
reference high frequency (hz)
19 LFReference (20.0 to 1000.0) default = 250.0
reference low frequency (hz)
20 RoomRolloffFactor (0.0 to 10.0) default = 0.0
like rolloffscale in System::set3DSettings but for reverb room size effect
21 Diffusion (0.0 to 100.0) default = 100.0
Value that controls the echo density in the late reverberation decay.
22 Density (0.0 to 100.0) default = 100.0
Value that controls the modal density in the late reverberation decay
23 Flags default = 63
Bit flags that modify the behavior of above properties
  • 1 - 'EnvSize' affects reverberation decay time
  • 2 - 'EnvSize' affects reflection level
  • 4 - 'EnvSize' affects initial reflection delay time
  • 8 - 'EnvSize' affects reflections level
  • 16 - 'EnvSize' affects late reverberation delay time
  • 32 - AirAbsorptionHF affects DecayHFRatio
  • 64 - 'EnvSize' affects echo time
  • 128 - 'EnvSize' affects modulation time

echo var (sound)

See also:
vars (sound)
x, y, z vars (sound)
environment var (sound)
Default value:
null

If set to an 18-element list, this value customizes reverbration settings for this sound only. A null or non-numeric value for any setting will select its default. Please see the EAX2 documentation at http://developer.creative.com/ for indepth information about these settings.

Here's a rundown of some of the terms: Direct refers to the amount of effect when the sound is on a direct path to the listener. Obstruction is when an object is blocking the direct path but there are other ways for the sound to reach the listener. Occlusion means the sound is on the other side of a wall, and mostly blocked. Exclusion means the sound is on the other side of a wall, but a doorway or window is allowing it to pass through to the listener. You can use a little of each of these effects to increase realism.

1 Direct (-10,000 to 1,000) default = 0
direct path level (at low and mid frequencies)
2 DirectHF (-10,000 to 0) default = 0
relative direct path level at high frequencies
3 Room (-10,000 to 1,000) default = 0
room effect level (at low and mid frequencies)
4 Room HF (-10,000 to 0) default = 0
relative room effect level at high frequencies
5 Obstruction (-10,000 to 0) default = 0
main obstruction control (attenuation at high frequencies)
6 ObstructionLFRatio (0.0 to 1.0) default = 0.0
obstruction low-frequency level re. main control
7 Occlusion (-10,000 to 0) default = 0
main occlusion control (attenuation at high frequencies)
8 OcclusionLFRatio (0.0 to 1.0) default = 0.25
occlusion low-frequency level re. main control
9 OcclusionRoomRatio (0.0 to 10.0) default = 1.5
relative occlusion control for room effect
10 OcclusionDirectRatio (0.0 to 10.0) default = 1.0
relative occlusion control for direct path
11 Exclusion (-10,000 to 0) default = 0
main exlusion control (attenuation at high frequencies)
12 ExclusionLFRatio (0.0 to 1.0) default = 1.0
exclusion low-frequency level re. main control
13 OutsideVolumeHF (-10,000 to 0) default = 0
outside sound cone level at high frequencies
14 DopplerFactor (0.0 to 10.0) default = 0.0
like DS3D flDopplerFactor but per source
15 RolloffFactor (0.0 to 10.0) default = 0.0
like DS3D flRolloffFactor but per source
16 RoomRolloffFactor (0.0 to 10.0) default = 0.0
like DS3D flRolloffFactor but for room effect
17 AirAbsorptionFactor (0.0 to 10.0) default = 1.0
multiplies AirAbsorptionHF member of environment reverb properties.
18 Flags default = 7
Bit flags that modify the behavior of properties
  • 1 - Automatic setting of 'Direct' due to distance from listener
  • 2 - Automatic setting of 'Room' due to distance from listener
  • 4 - Automatic setting of 'RoomHF' due to distance from listener

turf

See also:
atom
procs (turf)
vars (turf)
Map

Turfs cover the surface of the map. They are derived from /turf which derives from /atom.

This example defines the turf prototype /turf/floor and /turf/wall.

Example:

turf floor desc = "A wood plank floor." wall desc = "A stone wall." density = 1

Turfs cannot be moved. They can only be created or destroyed by changing world.maxx, world.maxy, or world.maxz. When you create a new turf with new(), it always replaces the old one.

Example:

// replace old_turf with a wall var/turf/wall/T = new(old_turf)

procs (turf)

Built-in turf procs:

turf/proc
Click
Cross proc
Crossed proc
DblClick
Del
Enter
Entered
Exit
Exited
MouseDown
MouseDrag
MouseDrop
MouseEntered
MouseExited
MouseMove
MouseUp
MouseWheel
New
Read
Stat
Topic
Write
Uncross proc
Uncrossed proc

vars (turf)

Built-in turf vars:

turf/var
alpha
appearance
appearance_flags
blend_mode
color
contents
density
desc
dir
filters
gender
icon
icon_state
invisibility
underlays
overlays
loc
layer
luminosity
mouse_over_pointer
mouse_drag_pointer
mouse_drop_pointer
mouse_drop_zone var
mouse_opacity var
name
opacity
parent_type
pixel_x
pixel_y
pixel_w
pixel_z
plane
render_source
render_target
suffix
tag
text
transform
type
vars
verbs
vis_contents
vis_flags
vis_locs
x
y
z

parent_type var (turf)

See also:
parent_type var

The default parent_type of /turf is /atom.


vars

See also:
path operators
vars (atom)
vars (client)
vars (datum)
vars (mob)

Variables are derived from var.

Variable Declaration Format:
var/Type/Name = Value
var Type/Name = Value

Value defaults to null.

The hard-coded types are:
datum (ancestor of all objects)
atom (all mappable objects)
atom/movable (objs and mobs)
obj
mob
turf
area
savefile
client
list
world
Type modifiers:
global
const
tmp
final

User types may be derived from anything except for /world, /list, /client, and /savefile.


const vars

See also:
vars

The const type modifier defines a constant value. This may be useful for centralizing the location of a value that is used repeatedly so that it can be easily configured. It has the advantage over #define macros of obeying the normal scope rules for variables. This means, for example, that a const variable declared inside a proc will not conflict with other variables declared elsewhere.

Example:

mob var/const/max_items = 100 Enter(O) if(src.contents.len >= src.max_items) return 0 return ..()

This example defines an upper limit on the number of items a mob may carry.


final vars

See also:
vars
const vars
global vars
tmp vars

The final type modifier indicates that a variable should not be overridden by a subtype or another compile-time assignment statement.

This modifier also applies to procs. A final proc may not be overridden.


global vars

See also:
vars

The global type modifier makes a var permanent and shared. This means only one copy of the var is maintained. Otherwise, separate copies of the var are maintained for each instance containing the var (be it a proc, mob, obj, etc.)

Example:

mob/proc/Counter() var/global/count src << "Count = [++count]"

This example increases the count each time the proc is called. If count were not declared global, the displayed count would be 1 every time.


tmp vars

See also:
savefile
vars

The tmp type modifier indicates that an object variable should not be automatically written to the save file. This could mean that the variable is transient—that is, it is calculated at run-time and need not be saved. It could also indicated that the designer will handle saving of that variable specially and wishes to bypass the automated routine.

It is especially important to use tmp when you have references to external objects that should not be saved along with the object. For example, suppose players have a leader variable which indicates who or what they are following. You would not necessarily want the leader to be saved in the player's savefile. Therefore, you would need to use tmp when defining the variable.

Example:

mob var/tmp leader verb follow(mob/M) leader = M
The following built-in variables are defined as tmp vars:
type
parent_type
vars
verbs
group
loc
locs
vis_locs
x
y
z
ckey
visibility
bound_x
bound_y
bound_width
bound_height
mouse_over_pointer
mouse_drag_pointer
mouse_drop_pointer

verbs

See also:
arguments (verb)
settings (verb)
vars (verbs)
src var (proc)
usr var (proc)

Verbs may be attached to mobs, objs, turfs, and areas. Players can then use them as commands if they have access to the source.

Verbs are fundamentally the same "type" as procs, so their vars are the same.

Example:

mob/verb/poof() world << "POOF!"

Whenever a player in the world types the command "poof", this verb will be invoked.

In addition to the normal access control (see the verb src setting) verbs can be dynamically added and removed from objects. One way to do this is to use new() with the following syntax:

new verb_path(Destination,Name,Desc)

The Destination specifies the object to receive the verb. Name and Desc optionally specify a new name and description for the verb.

Example:

mob/DM/verb/kill(mob/M) del(M) mob/DM/verb/give_kill_verb(mob/M) new/mob/DM/verb/kill(M)

This example defines two verbs (accessible to mobs of type /mob/DM). One verb kills other mobs. The other adds the kill verb to another mob (giving the second mob the ability to kill).

In some situations, the ability to dynamically change an object's verb list is quite useful, but most of the time it is far more convenient to do the same thing by manipulating objects rather than verbs directly. For example, the previous example can be handled by having an object with the kill verb attached it it. Then players have greater versatility in manipulating the verb by simply moving the object around.

Example:

obj/scroll/kill/verb/kill(mob/M) set src = usr.contents //implicit src del(M)

The use of an implicit verb source in this example gives the user access to the kill verb without having to specify the source scroll as long as the scroll exists in the user's inventory. In other words, the player types "kill rat" rather than "kill kill rat".


arguments (verb)

See also:
argument expanding
command_text (client)
arglist proc
args var (verb)

The parameters to a verb are referred to as arguments. For verbs, the input type and possible value list may also be specified.

The possible input types are:

text          // a quoted text string
password      // un-echoed text (for use with input() only)
message       // multi-line text
command_text  // raw command text from the rest of the input line
num           // a number
icon          // an icon file from the user's computer
sound         // a sound file from the user's computer
file          // any type of file from the user's computer
key           // a key from the user's BYOND key file
color         // a color (see rgb proc)
null          // indicates that the argument is optional

mob
obj
turf
area
anything

These can be combined with the '|' operator. The first group are called constant input types because they turn on various types of literal values that the user can type in (like a number or a text string). The second group work in conjunction with a list of objects or values. They are called input type filters because they may be used to filter out certain types of values from the list. For example a mob or an obj within sight would be specified as follows:

myverb(M as mob|obj in view()) {...}

A default value may be specified which takes effect in the case of null arguments. For example:

myverb(M=usr as null|mob|obj in view()) {...}

In this example, the input type null did not have to be used explicitly, because assigning a default value (in this case usr) turns it on by default.

The anything input type can be used to combine values in a list with other constant input types. Here, this is done with the null input type:

set_aggression(a="on" as null|anything in list("on","off"))

For input types containing mob, obj, turf, or area, the possible value list defaults to view().

If no input type is specified, the variable type will be used to determine whether it is a mob, obj, turf, or area.

Example:

mob/verb/tell(mob/M,msg as text) M << "[usr] tells you, /"[msg]/""

This example defines a verb with two arguments: a target mob, and some text.


argument expanding

See also:
arguments (verb)

The expression used to to provide a list of possible values for a verb argument may reference the value of arguments prior to the one being expanded. It may even reference the value of the argument being expanded, but this will always be a text string equal to what the user has typed so far.

In addition, there is a special variable called "expanding" which is only accessible in this context. It is 1 if the user's input is being expanded and 0 if the user's final input is being validated. In certain rare cases, you may wish to tell the difference between these two cases. For example, you could use this to have possible values which do not show up in the expansion lists, but which are accepted when typed in full.

Example:

mob/verb/test(A in MyProc(A,expanding)) usr << "You typed: [A]" proc/MyProc(A,expanding) var/values[] = list("one","two","three") if(!expanding) values += "secret" return values

settings (verb)

verb settings:

verb/set
  name
  desc
  category
  hidden
  popup_menu
  instant
  invisibility
  src
  background

Procs and verbs are the same "type" so these attributes may be set for procs as well; most of them do not have any meaning, however, unless the proc is invoked as a verb (by adding it to a verb list).


category setting (verb)

See also:
default_verb_category var (client)
show_verb_panel var (client)
Format:
set category = "Category"
Args:
Category: A text string for the category.

Verbs in the same category are visually grouped together in the verb panels. The default is "", which is displayed in the default panel titled "Commands". You can change that default by setting client/default_verb_category.

To hide a verb from all panels, set the category to null. The verb may still show up in right-click popup menus, so you may want to use the hidden or popup_menu verb properties instead.


desc setting (verb)

Format:
set desc = "Description"
Args:
Description: A text string containing the help text.

The desc attribute sets the descriptive help string for the verb. The player may access this by hitting the 'F1' key after entering the command. This will normally produce a list of each argument by type followed by the desc text. If you wish to override the syntax description, put your modified version inside parentheses at the beginning of the desc text.

Example:

mob/verb/tell(mob/M,T as text) set desc = "(target,message) Talk privately to someone." M << "[usr] tells you, '[T]"

This will produce the help text:

usage: tell target message (Talk privately to someone.)

If the syntax description had not been supplied, it would have produced:

usage: tell mob "text" (Talk privately to someone.)

hidden setting (verb)

See also:
category setting (verb)
invisibility setting (verb)
name setting (verb)
popup_menu setting (verb)
Format:
set hidden = Setting
Args:
Setting: 1 for hidden verbs; 0 otherwise.

A hidden verb is not visible to players (in menus or in expansion lists) but if typed in full can still be accessed.

An alternate way to hide a verb from the command-line and verb panels is to make "." the first character in the name. The verb will not show up in command-expansion (ie when hitting spacebar) until the "." has been typed. This could be useful for hiding verbs that would otherwise clutter up the verb list, while still making them relatively easy to use. If you think this is a random quirky feature, you are right. To put "." in front of the name, use the name setting.


instant setting (verb)

See also:
settings (verb)
Format:
set instant = Setting
Args:
Setting: 1 for "instant" verbs; 0 otherwise.
Default value:
0

Normally a player can only call one verb per tick, but they can call any number of "instant" verbs in the same tick. This setting is useful for commands called by the game's interface, or for more responsive controls like for instance the use of "combos" in fighting games.

Verbs with the instant setting can be used on the same tick as a regular verb, but only one regular verb can be used each tick. Instant commands will jump ahead of non-instant commands in the queue.

Any verbs that are already built-in, such as movement commands, cannot be modified to use this setting. (Some, such as mouse commands, already use it.) You can, however, create replacement verbs of your own for most of them.

Example:

mob/verb/FastNorth() set instant = 1 usr.Move(get_step(usr,NORTH), NORTH)

invisibility setting (verb)

See also:
hidden setting (verb)
invisibility var (atom)
sight var (mob)
Format:
set invisibility = Setting
Args:
Setting: 0 to 100
Default value:
same as invisibility of the source object.

An invisible verb is only accessible to players who can see invisible objects. This is different from a hidden verb which does not clutter up the verb list but which is still accessible when typed in full.


name setting (verb)

Format:
set name = "Name"
Args:
Name: A text string for the name.

The name attribute of a verb defaults to the node name. Setting the name attribute explicitly may be necessary if the name includes characters not allowed in node names.


popup_menu setting (verb)

See also:
category setting (verb)
hidden setting (verb)
invisibility setting (verb)
Format:
set popup_menu = Setting
Args:
Setting: 1 (default) for showing this verb in the popup menus; 0 otherwise.

Use this to prevent a verb from showing up in the popup "context" menu when users right-click on objects.


src setting (verb)

Format:
set src in List
set src = List
Args:
List: One of view(), oview(), world, world.contents, usr, usr.contents, usr.loc, or usr.group

With the first format, if src is in List for a particular player, then that player will have access to the proc. The player must explicitly specify the name of the source on the command line.

The second format behaves the same, except the source is not read from the command line. If more than one possible source exists, one will be chosen at random.

When usr or world is specified for the first format, it will be expanded to usr.contents and world.contents respectively.

The default setting depends on the type of src:

mob: src = usr obj: src in usr // short for usr.contents turf: src = view(0) area: src = view(0)

Example:

obj/verb/examine() set src in view() usr << "You examine [src]."

Example:

obj/MagicCloak/verb/disappear() set src = usr.contents usr.invisibility = 1 view() << "[usr] disappears!"

visibility setting (verb)

See:
invisibility setting (verb)

The function of this variable has been replaced by invisibility, which provides a full range of settings.


vars (verbs)

See:
vars (procs)

. var (verb)

See:
. var (proc)

args list var (verb)

See:
args list var (proc)

src var (verb)

See:
src var (proc)

usr var (verb)

See:
usr var (proc)

world

See also:
procs (world)
vars (world)

The world node is used to define some global properties for the world. Like the other types, the world has overridable vars and procs. New vars and procs cannot be defined under world though; to make global vars and procs, use /var and /proc instead.


procs (world)

Built-in world procs:

world/proc
AddCredits
ClearMedal
Del
Export
GetConfig
GetCredits
GetMedal
GetScores
Import
IsBanned
IsSubscribed
New
OpenPort
PayCredits
Profile
Reboot
Repop
SetConfig
SetMedal
SetScores
Tick
Topic

AddCredits proc (world)

See also:
GetCredits proc (world)
PayCredits proc (world)
Format:
AddCredits(player, credits, note)
Returns:
1 if the credits were added successfully, 0 or null otherwise.
Args:
player: a mob, client, key, or ckey
credits: A number of credits to add to the player's account
note: An optional note (for author purposes) for the credit change

Adds credits to a player's account. The proc will return 1 if it is successful, or 0 if the attempt failed and should not be tried again. This feature is intended for games that make use of the credit system, and for security all such games must use a hub password.

This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

Example:

mob/proc/QuestCompleted(name, credits) src << "Congratulations! You completed the [name] quest and earned [credits] credit\s!" world.AddCredits(name, credits, "Quest: [name]")

Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.


ClearMedal proc (world)

See also:
GetMedal proc (world)
SetMedal proc (world)
GetScores proc (world)
SetScores proc (world)
Format:
ClearMedal(medal, player)
Returns:
1 if the medal was rescinded successfully, 0 or null otherwise.
Args:
medal: name of the medal being rescinded
player: a mob, client, key, or ckey

Removes a medal from a player. The proc will return 1 if it is successful, or 0 if the medal was not already awarded. If the world already knows this medal was not earned, the hub will not be contacted.

This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

Example:

mob/NPC Die(mob/killer) // assume Die() is a proc all mobs have spawn() if(ismob(killer) && killer.key) world.ClearMedal("Pacifist", killer)

Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.


Del proc (world)

See also:
Del proc (datum)
shutdown proc
Format:
Del()
When:
Called when the world is shutdown.
Default action:
Shutdown the world.

When the world is destroyed, only the Del() proc of the world object is called automatically. If you want to delete any other objects, you must do so from within world/Del(). Once this procedure returns, any other procedures which may still be executing are immediately aborted and all objects are silently destroyed.

To prevent accidental hangs during world/Del() from preventing shutdown, a timeout is applied to any sleeping operations such as sleep, world.Export(), and so on. If the total time slept exceeds the timeout, world/Del() is aborted. Currently, this timeout is set at 30 seconds.


Error proc (world)

See also:
try and catch statements
throw statement
exception
Format:
Error(exception)
Args:
exception: The error that was thrown. If this was a runtime error, the value will be an /exception datum.

Called when a runtime error happens, or the throw keyword is used, without a try/catch to handle it. The return value is ignored.


Export proc (world)

See also:
Export proc (client)
Import proc (world)
Topic proc (world)
link proc
shutdown proc
Format:
Export(Addr,File,Persist,Clients)
When:
Call this to send a message to another server. The message may be composed of an optional topic text string (in the address) and an optional file. This will call world.Topic() on the remote server, which may in turn call world.Import() to access the file.
Args:
Addr: The address of the recipient server. It should be in the form byond://server?topic. The topic portion is optional.
File: The (optional) file to send. This could be a cache file (in single quotes) an external file (in double quotes) or a savefile.
Persist: Set to 1 to indicate that the server should keep this connection open, to expedite subsequent calls to the same address. An open connection can be closed at a later time by passing 0 in the Persist field.
Clients: An optional client, or list of clients, to tell the receiver about.
Default action:
Send the topic text string and file to the remote server and return the result of calling world.Topic() there. Note that this will cause the caller to sleep while waiting for the necessary data to be transfered.

Example:

mob/verb/shout(Msg as text) world << Msg world.Export("[ShadowWorld]?shout:[Msg]")

This example defines a verb that will broadcast a message to everyone in this world as well as sending it in the form of topic text to another world whose address is stored in the variable ShadowWorld. This address could be manually set or could be the result of calling startup().

It is also possible to access an HTTP server via world.Export(). Simply use an http address such as: http://www.byond.com. This returns a list of HTTP header parameters as well as the extra values "STATUS" and "CONTENT". The value associated with the "STATUS" entry is the HTTP status code returned by the web server (as text). The value associated with the "CONTENT" entry is the requested resource.

Example:

mob/verb/test() var/http[] = world.Export("http://www.byond.com") if(!http) usr << "Failed to connect." return usr << "HTTP Header:" for(var/V in http) usr << "[V] = [http[V]]" usr << "\n" var/F = http["CONTENT"] if(F) usr << html_encode(file2text(F))

Note that the HTTP request is submitted using the GET method as opposed to the POST method. Support for POST may be added in the future.

If the Clients argument is used, it accepts a client that is currently loggedin, a mob belonging to such a client, or a list of any of these. The remote server will receive a list of their keys in world.Topic().


GetConfig proc (world)

See also:
IsBanned proc (world)
SetConfig proc (world)
Format:
GetConfig(config_set,param)
Returns:
Value of requested parameter.
Args:
config_set: name of the configuration set (see below)
param: name of the configuration parameter

This command is for retrieving configuration information that is shared by applications installed on the same system. The configuration data is accessed by specifying the configuration "set" and the parameter within that set. The "sets" defined so far are:

env system environment variables (changes are not persistent) admin list of site administrators ban list of banned users or IP addresses keyban list of banned users (deprecated) ipban list of banned addresses (deprecated)

If no parameter is specified, a list of the names of all available parameters is returned.

The format of the configuration data itself is currently being defined. It will generally be a sequence of parameters (such as produced by list2params()). For example, each ban entry would have the user's ckey or ckeyEx as the parameter, and might have data such as "reason=jerkish;message=You+jerk!".

Example:

mob/verb ban(key as text) world.SetConfig("ban",ckey(key),"reason=fiendish;admin=[ckey]") lookban(key as null|text) if(key) usr << "[key]: [world.GetConfig("ban",key)]" else var/lst[] = world.GetConfig("ban") for(key in lst) usr << "[key]: [world.GetConfig("ban",key)]"

Ban files store information on a game-specific basis. You will only be able to read and write values that are set for the game you are running (defined by the value of world.hub). It is possible for a host to specify universal bans as well, but these will not be accessible via GetConfig or SetConfig. If you are using "ban" as the config_set, IP addresses are recognized automatically. (See the ban format info below.)

It is possible, but rarely useful, to specify a configuration "space" of SYSTEM, USER, HOME, or APP. Settings made in the SYSTEM space are shared by all BYOND software on the computer. The USER space is shared by all software owned by the same user. The HOME space is shared by all worlds running with the same safe home directory. The APP space is shared by all software running from the same filesystem directory. By default, the USER space is used, and if that cannot be modified (in safe mode), then HOME is used instead. These distinctions are sometimes important on a UNIX machine, where there are many BYOND sites belonging to different users, but even then, the default behavior is almost always what you want.

The configuration space is specified inside the configuration set parameter like this:

world.SetConfig("APP/keyban",...)

When reading configuration settings, the spaces are always lumped together. In cases of settings with the same name but different values, APP overrides HOME, which overrides USER, which overrides SYSTEM.

Ban Format

If you want to create or read bans at runtime by using the "ban" config set, these are the main parameters currently used:

type
The ban's type, if any. It can be "sticky", "session", or "time", or a combination separated by commas. Session bans expire when the current session is over (world.Reboot() does not affect this).
reason
The reason the ban was implemented; this is for the host's or admin's purposes only and is not displayed to the user.
message
A message to display to the user.
keys
Other keys caught in a sticky ban.
IP
Other IP addresses caught in a sticky ban.
computer_id
Other computer_id values caught in a sticky ban.
time
The number of seconds remaining in the ban. The type parameter must include "time" for this to mean anything. If this parameter is not present when a timed ban is read, it means the ban has expired.

The old "keyban" and "ipban" config files are now just aliases for "ban".


GetCredits proc (world)

See also:
AddCredits proc (world)
PayCredits proc (world)
Format:
GetCredits(player)
Returns:
Number of credits if hub contact was successful, null otherwise.
Args:
player: a mob, client, key, or ckey

Retrieves the number of available credits in a player's account. This feature is intended for games that make use of the credit system, and for security all such games must use a hub password.

This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

The best time to call this proc is before a player does something that would allow them to spend credits, and/or just afterward, so they can see what is left in their account.

Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.


GetMedal proc (world)

See also:
SetMedal proc (world)
ClearMedal proc (world)
GetScores proc (world)
SetScores proc (world)
Format:
GetMedal(medal, player)
Returns:
1 if the medal has been earned by the player
0 if the medal has not been earned
A list of medals in list2params() format if checking all medals
null if the hub cannot be contacted
Args:
medal: name of the medal being checked
player: a mob, client, key, or ckey

Checks to see if a medal has been awarded to the player in question. If the medal has been awarded, the return value is 1. If not, 0.

You can also use GetMedal() to read a list of all medals a player has earned for the hub entry, by leaving the medal argument blank. If you also leave the player argument blank, you will get a list of all medals available to the hub entry. In both cases the result can be parsed with params2list().

This proc will return null if there was no way to reach the hub or otherwise verify the medal's status. Use isnull() to check for a null value.

Whenever possible, GetMedal() will avoid contacting the hub by using the information it was given when the user logged in. If contacting the hub is required, the proc may take a few moments to return a result. It is a good idea to use spawn() to avoid holding up the rest of the game.

Example:

turf/medal_door density = 1 icon_state = "closed" var/medal = "Dragon slayer" verb/Knock() usr << "<b>Guard:</b> Just checking your credentials...." var/hasmedal = world.GetMedal(medal, usr) if(hasmedal) usr << "<b>Guard:</b> Go right in." icon_state = "open" density = 0 else if(!isnull(hasmedal)) usr << "<b>Guard:</b> Sorry, no admittance without a <b>[medal]</b> badge." else usr << "<b>Guard:</b> Sorry, I lost the paperwork. Try again later."

You can add an optional hub path argument if you want to look at a medal for a different hub entry.


GetScores proc (world)

See also:
SetScores proc (world)
GetMedal proc (world)
SetMedal proc (world)
ClearMedal proc (world)
Formats:
GetScores(key, fields)
GetScores(count, field)
GetScores(count, skip, field)
Returns:
A parameter list of scores for a given entry. Use params2list() to interpret the results.
Args:
key: the name of the player, character, etc. for which scores have been set
fields: The data fields to retrieve
count: The number of top score records to look at
skip: The number of top score records to skip over

Retrieves information about scores that is kept on the BYOND hub.

This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

GetScores(key, fields)

In this form, you can get information about individual scores. This is the most common way to use GetScores().

The key is an arbitrary text value. Usually a player's key is a good choice, but you can also use the name of their character, or anything else you like, as long as it is unique. The key is case-insensitive.

Scores and stats use data fields, which might be things like "Score", "Level", "Class", etc. To retrieve all the fields associated with a key, leave the fields argument blank. To retrieve only certain fields, you can send a separated list like "Score;Level" which is in the same format returned by list2params().

If you leave the key argument blank, you will get a complete list of keys that have scores and stats associated with them.

Example 1:

mob/var/scores_found mob/var/score = 0 mob/Login() ..() spawn() var/scores = world.GetScores(key) scores_found = !isnull(scores) if(scores) var/list/params = params2list(scores) if(params["Score"]) score = text2num(params["Score"]) src << "You have [score] point\s!"

GetScores(count, field)
and GetScores(count, skip, field)

In this form, the proc gets a list of the top scores for a certain field, and gives you the keys and scores in order. To get the top 10 players by level, for instance, you would use GetScores(10,"level"). This returns a parameter list with the top keys and scores, so it might be in a form like "Bob=100;Anita=80;David=20;Charlie=5".

The count and skip arguments are always numbers, not text. The count is the number of scores to retrieve, and skip is the number to skip over to get to them. So count=10 and skip=0 is the top 10, while count=10 and skip=5 is #6 through #15. If you leave out skip, it's a 0.

The way you set up your hub entry is how the top scores are determined. If you told the hub that the "score" field is always sorted from highest number to lowest, then that's what you'll get. If "birthplace" is set up to use an alphabetical order, that's the order that GetScores() will use. If a field cannot be sorted, this form of GetScores() will return an empty text string.

If you don't specify a field, your hub entry may have a default field to use. For instance if your hub page displays "Score", then "Level", then the "Score" field is the default.

Example 2:

mob/var/scores_found mob/Login() ..() spawn() var/top_scores = world.GetScores(10, "Booty") scores_found = !isnull(scores) if(scores) var/list/params = params2list(scores) src << "<b>Top Buccaneers:</b>" for(var/i=1, i<params.len, ++i) var/player = params[i] var/loot = params[player] src << "[i]\th place: [player] with [loot] doubloon\s" if(params.len && params[1] == key) src << "Ye be master of the seas! Take thy well-earned hat." icon_state = "Commodore"

Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.


Import proc (world)

See also:
Export proc (world)
Import proc (client)
Topic proc (world)
fcopy proc
Format:
Import()
Returns:
The file sent by the remote server. The file will be downloaded to the local server's resource cache. Note that this will cause the caller to sleep while waiting for the necessary data to be transfered.
When:
Call this inside world.Topic() if you are expecting a file from the remote server.

Example:

//sending the file mob/proc/Export(Addr) var/savefile/F = new() F.Write(src) world.Export(Addr,F) //receiving the file world/Topic() var/savefile/F = new(world.Import()) F.Read() //read the mob

This example defines a mob proc called Export() which writes the mob to a savefile and sends it to another server (specified by Addr). The remote server opens it as a savefile and creates the mob (if the same mob type is defined on both servers and mob.Read() is compatible with the sending server's mob.Write()).

Note that another method of transferring player mobs is to use the key savefile (accessed by client.Export() and client.Import()). Direct server to server communication on the other hand could transfer data (like non-players) without the need for player involvement at all.

Savefiles are the most common type of file to transfer, but world.Import() simply returns a reference to an item in the world's .rsc file, which could be any type of file. This particular example demonstrates how to open such a file as a temporary savefile. (It gets dumped from the cache into a separate temporary file, which is then opened as a savefile.) Other types of files would be handled differently. For example, you could use fcopy() to dump the cached item to its own separate file.


IsBanned proc (world)

See also:
GetConfig proc (world)
params2list proc
address var (client)
computer_id var (client)
connection var (client)
hub var (world)
Format:
IsBanned(key,address,computer_id,type)
Returns:
True value if user is banned from this world. This may be a list, in which case special meaning is attributed to certain list elements as described below.
Args:
key: BYOND key of the user.
address: current IP address of the user.
computer_id: current computer_id of the user if known.
type: type of connection if known (see client.connection)

By default, this procedure checks the "ban" configuration file. If an entry is found for the current world (based on the value of world.hub), the parameter text is converted into a list (using params2list()), and the result is returned. Otherwise, null is returned.

A ban that applies to all worlds on the host's computer will not call IsBanned(). The connection will simply be denied.

This procedure is called internally whenever a new user connects (before client/New() is called). If the result is true, access is denied. If you want to ban a user but still allow them to log in (perhaps with reduced functionality), you can put "Login=1" in the parameter text. If you want to display an explanation to the user about why they are banned, you can also put "message=X" in the parameter text, where X is the message to display to the user. A reason for the ban can be added with a "reason=X" field. Of course, you can also override IsBanned() and insert these values directly into the list that is returned.

Example

world/IsBanned(key,address) . = ..() //check the ban lists if(istype(., /list)) .["Login"] = 1 //allow banned user to login

When you ban people from paging you, this also causes them to be added to the keyban list. Even if they are already connected, IsBanned() will be re-evaluated and acted upon at that time. When you remove pager ban, they are removed from keyban as well.

Additional data elements may be added to the ban list in the future. The current definition includes just the following items:

Login
true if banned user should be allowed to log in
reason
text string describing the reason or origin of the ban. For example, when people are banned from the pager, they are added to the "keyban" list with reason = "pager ban". This text is internal information only and is not displayed to the banned user.
message
text string explaining to the user why they were banned and possibly what they should do to be forgiven.

Since the data in the "ban" file is in application/x-www-form-urlencoded format, it is probably not desirable to edit the file by hand. No built-in facilities for editing the file have been provided (aside from automatic addition of pager bans), but an interface could be created, using GetConfig and SetConfig to read and write the data. Extra features could also be added such as automatic inference of key associations by IP address.


IsSubscribed proc (world)

Format:
IsSubscribed(player)
IsSubscribed(player, "BYOND") (to check BYOND Membership)
Returns:
Number of days left in subscription, -1 for a lifetime subscriber, or null if hub contact failed
Args:
player: a mob, client, key, or ckey

Checks a player for their subscription status to this game. This is a simpler alternative to client.CheckPassport(), which is deprecated, and also allows you to check even when the player has gone offline.

This proc will return null if contacting the hub was required, but there was no way to reach the hub. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

Example:

mob/verb/JoinClub() if(!world.IsSubscribed(src)) src << "Sorry, the club is only for subscribers." else // go to the turf with the tag "clubhouse" loc = locate("clubhouse") src << "Welcome to the clubhouse!"

Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.


New proc (world)

Format:
New()
When:
Called after the world is initially loaded. The only procs preceding this one would be in the initialization of global variables and objects on the map.
Default action:
None.

OpenPort proc (world)

See also:
port var (world)
visibility var (world)
See also:
OpenPort(port=0)
Args:
port: the network port to open
Returns:
1 on success; 0 on failure

This causes the world to be hosted on the specified network port. A value of 0 or "any" requests that any available port be used. The value "none" causes the port to be closed so that no new connections are possible.

This proc may be overridden. If it is, calling ..() is necessary to open the port. If ..() is not called, it will not open.

Example:

world/OpenPort(port) // only allow subscribers to host if(host_is_subscribed) return ..()

The "ports" configuration option in cfg/byond.txt can be used to control what ports worlds may open. The -ports command-line option may also be used. See startup for the syntax.


PayCredits proc (world)

See also:
AddCredits proc (world)
GetCredits proc (world)
Format:
PayCredits(player, credits, note)
Returns:
1 if the credits were spent successfully, 0 or null otherwise.
Args:
player: a mob, client, key, or ckey
credits: A number of credits to deduct from the player's account
note: An optional note (for author purposes) for the credit change

Removes credits from a player's account, if they have enough. The proc will return 1 if it is successful, or 0 if the attempt failed (usually because the player doesn't have enough credits). This feature is intended for games that make use of the credit system, and for security all such games must use a hub password.

This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is often a good idea to use spawn() to avoid holding up the rest of the game.

Example:

mob/proc/ItemShop() var/items = list("Get credits!", "Magic sword"=10, "Skeleton key"=50) var/choices[0] var/item,price for(item in items) price = items[item] choices["[item]: [price] credit\s"] = item var/credits = world.GetCredits(key) if(isnull(credits)) src << "Sorry, the item shop isn't available right now." return var/choice = input(src,\ "You have [credits] credit\s. What would you like to purchase?",\ "Item Shop")\ as null|anything in choices if(!choice) return // cancel if(choice == "Get credits") src << link("http://www.byond.com/games/Author/MyGame/credits") return item = choices[choice] price = items[item] if(!price) return src << "Contacting item shop..." var/result = world.PayCredits(name, price, "Item shop: [item]") if(isnull(result)) src << "Sorry, the item shop isn't available right now." else if(!result) src << "You need [price-credits] more credit\s to buy [item]." else src << "You bought \a [item]!" // Now give the user the item and save their character // These procs are for you to define src.AddEquipment(item) src.SaveCharacter()

Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.


Profile proc (world)

Format:
Profile(command, format)
Profile(command, type, format)
Returns:
Profilng data or null
Args:
command: A numerical value that says whether to start, stop, refresh, etc.
type: A type of profile to use, other than proc profiling.
format: Optional format for output data

Interacts with the built-in server profiler without requiring the host to do so via Dream Daemon, or an authorized player via Dream Seeker.

The command value is built from bitflags, so it can combine any of these three values via the | operator:

PROFILE_STOP
Stop profiling. Not using this flag will start/continue profiling.
PROFILE_CLEAR
Clear all profile data. This will also cause the proc to return null.
PROFILE_AVERAGE
Any output data should use average times instead of total times.

These additional values are also defined for convenience:

PROFILE_START
Start/continue profiling but don't clear any existing data.
PROFILE_REFRESH
Currently this is the same as PROFILE_START.
PROFILE_RESTART
Start profiling and clear existing data.

Profiling procs

By default, data will be returned as a list. The first six values are the column names: "name", "self", "total", "real", "over", and "calls", corresponding to the columns in the profiler. These are followed by the profile data for each proc, with the data being in the same column order. E.g. the next six items represent the first proc in the profile.

The optional format argument however can be used to return the data in other formats. Currently the only accepted value is "json", which will output the same data in JSON format.

SendMaps profile

Using "sendmaps" in the type argument will profile the routines used to send map informaiton to players. Unlike the proc profiling this only has three data columns: "name", "value", and "calls". The value column might be a time or number value, depending on what's being measured.

The JSON format will include a unit property data that is not a raw number, such as a time value.


Reboot proc (world)

Format:
Reboot(reason)
Args:
reason: the reason Reboot() was called:
Default action:

Reload the world from scratch. Any connected players will automatically relogin. This would be useful if you needed to recompile the world after changing some code.

In a UNIX environment, you can cause a running server to reboot by sending it the signal SIGUSR1.

If you override this proc, you must call ..() if you want the reboot to complete normally.

For reboots initiated by Dream Seeker, usr will be the mob belonging to the player who sent the command.


Repop proc (world)

Format:
Repop()
Default action:
Reload the obj and mob instances defined in the world map. This "repopulates" a world to its initial state. Only objects that were destroyed will be recreated.

SetConfig proc (world)

See also:
GetConfig proc (world)
Format:
SetConfig(config_set,param,value)
Args:
config_set: name of the configuration set (see below)
param: name of the configuration parameter
value: data to store (or null to delete this entry)

This command is for storing configuration information that is shared by applications installed on the same system. The configuration data is accessed by specifying the configuration "set" and the parameter within that set.

For more information, see GetConfig.


SetMedal proc (world)

See also:
GetMedal proc (world)
ClearMedal proc (world)
GetScores proc (world)
SetScores proc (world)
Format:
SetMedal(medal, player)
Returns:
1 if the medal was awarded successfully, 0 or null otherwise.
Args:
medal: name of the medal being awarded
player: a mob, client, key, or ckey

Awards a medal to a player. The proc will return 1 if it is successful, or 0 if the medal was already awarded. If the world already knows this medal was earned before, the hub will not be contacted.

This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

Example:

mob/monster/dragon Die(mob/killer) // assume Die() is a proc all mobs have spawn() if(ismob(killer) && killer.key) world.SetMedal("Dragon slayer", killer)

Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.


SetScores proc (world)

See also:
GetScores proc (world)
GetMedal proc (world)
SetMedal proc (world)
ClearMedal proc (world)
Format:
SetScores(key, fields)
Returns:
The key, if the scores were successfully updated; null otherwise.
Args:
key: the name of the player, character, etc. for which scores should be set
fields: The data fields to set

Updates scores that are kept on the BYOND hub.

The key is an arbitrary text value. Usually a player's key is a good choice, but you can also use the name of their character, or anything else you like, as long as it is unique. The key is case-insensitive.

Scores and stats use data fields, which might be things like "Score", "Level", "Class", etc. Use list2params() to set the fields that you want to change. Fields that you do not include in the list will not be changed. A field with a blank value will be deleted.

Sending an empty text string for the fields will erase the scores for that key.

This proc will return null if there was no way to reach the hub. Use isnull() to check for a null value. Contacting the hub may take a few moments, so it is a good idea to use spawn() to avoid holding up the rest of the game.

Example:

var/params // Change the Score and Pet fields params = list("Score"=123, "Pet"="Dog") world.SetScores("Tom", list2params(params)) // Delete the Pet field params = list("Pet"="") world.SetScores("Tom", list2params(params)) // Delete Tom's scores entirely world.SetScores("Tom", "")

Note: You can specify a different hub path and hub_password by adding these as extra arguments, but this is not recommended for security reasons. If you use this feature, it should only be on games that cannot be downloaded by the public.


Tick proc (world)

See also:
cpu var (world)
map_cpu var (world)
tick_usage var (world)
Format:
Tick()
When:
Called during the server tick, after sleeping procs and queued commands, just before map information is sent to the clients.
Default action:
None.

This proc allows you to do any updates just before map info is sent out. One possible use for this is to run a movement loop, or sync up any user interface input that might have arrived and deal with it all at once.

Example:

world/Tick() for(var/client/C) if(C.mob?.move_dir) try step(C.mob, move_dir) catch // empty catch, just so a failed step won't break the loop

Note: The tick will not wait if this proc sleeps. It effectively has set waitfor=0 already built in. It's a good idea not to sleep in this proc or any of its callees at all, since it will keep getting called every tick.


Topic proc (world)

See also:
Del proc (world)
Export proc (world)
Import proc (client)
Import proc (world)
Reboot proc (world)
Format:
Topic(T,Addr,Master,Keys)
When:
Called when a message is received from another server by using world.Export(). If a file is expected, world.Import() may be called to get it. The return value of Topic() will be passed back to the remote server.
Args:
T: The topic text string specified by the remote server (everything following ? in the URL).
Addr: The address of the remote server.
Master: 1 if remote server is the server which started this one.
Keys: List of keys belonging to users who are logged in on the remote server
Default action:
The topic "ping" returns a true value (number of players plus one), which may be useful for telling if a server is alive. The topics "Reboot" and "Del" will call world.Reboot() and world.Del() respectively if the message was sent by the master server.

Example:

world/Topic(T) if(findtext(T,"shout:") == 1) world << copytext(T,7)

This example allows other servers to send this server topic text of the form "shout:msg" and will broadcast the message to all the players in this world.

The Keys argument is either null, or a list of user keys. Any keys in the list are logged in to the remote server.

Always validate the input in Topic() calls to make sure it's correct and the query you're recieving is legitimate.


vars (world)

Built-in world vars:

world/var
address
area
byond_build
byond_version
cache_lifespan
contents
cpu
executor
fps
game_state
host
hub
hub_password
icon_size
internet_address
log
loop_checks
map_format
map_cpu
maxx
maxy
maxz
mob
movement_mode
name
params
port
process
realtime
reachable
sleep_offline
status
system_type
tick_lag
tick_usage
time
timeofday
timezone
turf
url
vars
version
view
visibility

address var (world)

See also:
port var (world)
url var (world)
internet_address var (world)

This is the network address of the machine hosting the world. If it cannot be determined, it will be null.

The full network address of the world may be formed by concatenating the world address and port: "byond://[address]:[port]".

In CGI mode, this is the web address of the world.

This is the local address only. If the world is hosted via a router, the external IP address may be different. Use internet_address to find the external address, if available.


area var (world)

Default value:
/area.

This is the default area type to be placed on the map wherever no area is specified. A value of 0 turns off the default area.


byond_build var (world)

See also:
DM_VERSION macro
byond_version var (world)
byond_version var (client)
byond_build var (savefile)
byond_version var (savefile)

This is the build number (minor version) of BYOND being run by this server. Typically this is not useful information, but it can come in handy when diagnosing issues reported by players when hosting with a beta build.


byond_version var (world)

See also:
DM_VERSION macro
byond_build var (world)
system_type var (world)
byond_version var (client)
byond_build var (savefile)
byond_version var (savefile)

This is the version of BYOND at run-time. A game designed to work around known bugs in older versions could use this to adapt its behavior accordingly.


cache_lifespan var (world)

See also:
cache
Default value:
30 (days)

Number of days items that are not in use will be saved in the resource cache (.rsc file). Files uploaded by players are stored in the world's .rsc file for future use. If the file is not used for the specified amount of time, it will be removed to save space.

Setting this value to 0 causes items to be saved for the current session only. This is used by the CGI library, because web browsers cannot make use of server-side caches when uploading files anyway.

This value must be a whole number.


contents list var (world)

See also:
list
Default value:
List of all areas, turfs, mobs, and objs initially in the world.

This is a list of every object in the world. Objects in this list are in no particular order.

Example:

proc/ListAreas(mob/M) var/area/A M << "Areas:" for (A in world.contents) M << A

This example displays a list of every area in existence. As a convenient short-hand, one may simply write for(A) or for(A in world) instead of the full for(A in world.contents).


cpu var (world)

See also:
map_cpu var (world)
tick_lag var (world)
tick_usage var (world)
Tick proc (world)

This is the percentage of a server tick that the server spends processing running procs and the work of sending map information to players. A value of 0 would indicate very little cpu usage. A value of 100 would indicate full cpu usage, which could mean that the server cannot complete all the necessary computations during a tick to finish in time for the next tick. In this case, timed events (such as sleep) may take longer than requested.

When deciding on a value for tick_lag, one could use this value to determine if the CPU is fast enough to tick at a higher rate.

The map_cpu var is a subset of this, measuring only time used for sending map information.


executor var (world)

See also:
startup proc
Format:
executor = "/usr/local/byond/bin/DreamDaemon [params]"

This option is for direct execution of .dmb files in UNIX. The most common use is for writing CGI programs that are executed by the web server.

The first parameter in the executor text string is the path to DreamDaemon. The one listed above is the standard UNIX location.

Optional parameters may follow. The most common are -CGI and -logself.

Example:

world/executor = "/usr/local/byond/bin/DreamDaemon -CGI -logself"

This example creates a CGI program to be executed by a web server. It puts its error output in the file projname.log.

All of this is configured for you when you include html/CGI.dm from the html library.


fps var (world)

See also:
tick_lag var (world)
fps var (client)
Pixel movement
Default value:
10

The value of world.fps defines the speed of the world in frames (server ticks) per second. By default this is 10 fps, which is a good speed if all objects move in full tiles. Higher values yield smoother results, but at a cost to performance. Timing of many events may be limited by the system clock, so fps values beyond 40 or 50 may cause unwanted effects like jitter even for projects that are not very demanding in terms of performance.

For projects making use of pixel movement, higher fps is usually desired. 40 seems to be a good value for general use, but in worlds that have a large number of players, you may wish to lower the value and give players a higher step_size per tick instead.

This var exists for convenience; it is calculated by 10 / world.tick_lag. The value of world.tick_lag is actually more accurate, but it is easier to think of world speed in terms of frames per second. The actual tick rate has a resolution of 1 ms.

When reading world.fps, the result is always given as a whole number to gloss over rounding error.

If you set client.tick_lag or client.fps to a value other than 0, you can make the client tick at a different (usually faster) rate.


game_state var (world)

See also:
name var (world)
status var (world)
visibility var (world)
Default value:
0

At runtime, this value may be changed to let the BYOND hub know about certain changes in the game's status. An example for using this value is if the number of players in the game gets too high and most new logins are rejected, you can set game_state to 1 to let the hub know this server is full.

The following values are accepted:

0
Normal status
1
Server is full

Note that this value does not affect how your world actually reacts to new players logging in. It is only used by the hub and website.


host var (world)

See also:
game_state var (world)
name var (world)
status var (world)
visibility var (world)
Default value:
null

If the information is made available by the pager, this will provide the key of the world's host. If the host is not known, this value will be either null or an empty string.


hub var (world)

See also:
hub_password var (world)
name var (world)
status var (world)
game_state var (world)
version var (world)
visibility var (world)
Default value:
null

This is a registered BYOND hub path. The default value of null is for unregistered games. Registered games (don't worry, it's free!) have their own hub page showing a brief description of the game, the author, an optional installation package, and links to online games. The hub path is a string of the form "YourName.GameName" and can be found in your hub console.

Even unregistered games show up in the hub when they are live (that is online with people connected). It just doesn't show any of the extra info like a description, and there is no way for people to find out about it when nobody is logged in.

If you do not want your game to show up in the hub (like while you are in the initial stages of development), just compile with visibility=0. Either that, or turn off your pager or your BYOND locator when you are connected to it.

You (or the players) might also wish to turn off the notice of a live game in the hub when there is no longer any room for new players or if it is too late in the game for new people to join. At such times, you can simply set the visibility to 0.

Example:

world hub = "Dan.PipeStock" //registered hub path mob/verb/start_game() world.visibility = 0 //...

If you configure your hub page to require a hub password, you must also specify world.hub_password.


hub_password var (world)

See also:
hub var (world)
visibility var (world)
Default value:
null

If world.hub is set, any live session of the game will be attached to the specified BYOND Hub page. Under the default settings, any game can set world.hub and attach itself to any BYOND Hub page.

To beef up security, you can set a hub password in your hub's configuration page via the BYOND website. This will ensure that only authorized copies of your game can attach themselves to your hub page when live. Then simply copy that password into your code as world.hub_password so that your game's live broadcast will be accepted by the hub.

Example:

world hub = "Dan.PipeStock" //registered hub path hub_password = "UPAggnJaeXmSBoKK" //password for live game authentication

Note that for security reasons, reading this variable at runtime will return a hashed version of the value that was set.


icon_size var (world)

See also:
map_format var (world)
step_size var (movable atoms)
Gliding
Pixel movement
Default value:
32

This is the tile size that will be used as a default for icons in the world. It can be set to a single number that represents both the width and height, or you can use a format like "[width]x[height]" (such as "16x48") to specify width and height separately.

This value affects several calculations, including icon operations and gliding between turfs.

Note: If you do not use a square icon size and you are using a topdown map format, you may experience display issues if setting client.dir to EAST or WEST. A non-square tile with a topdown map format will also interfere with pixel movement. For this reason, square sizes are recommended when using any topdown-view map format.


internet_address var (world)

See also:
port var (world)
url var (world)
address var (world)

This is the network address of the machine hosting the world, as it is seen by the outside network (from the Internet) and the hub. If it cannot be determined, it will be null.

The full network address of the world may be formed by concatenating the world address and port: "byond://[address]:[port]".

This var exists because world.address may not be accurate if the world is hosted on a machine behind a router using NAT. The value returned by internet_address can be given to other players who wish to log in.


log var (world)

See also:
file proc
startup proc

Sending output to world.log may be useful for debugging purposes. The output goes to the same place run-time proc errors are displayed.

Example:

if(1+1 != 2) world.log << "Uh oh."

You can assign world.log to a file name or file() object to redirect output to that file. (There is also a command-line option to Dream Daemon that does this.)

Example:

world.log = file("mylog.txt")

loop_checks var (world)

Default value:
1

Setting this to 0 disables the very long loop protection. By default, loops in the code which undergo a very large number of iterations or recursions are aborted (by crashing the proc). This prevents the proc from locking up the server for too long.

You may need to disable this feature if your code has some very long loops in it. Before doing that, make sure it's not infinitely long! Your program will utterly crash if it runs out of system stack space, which can happen in a very deep or infinite recursion.

Note: The compiler will now generate a warning when you disable loop_checks. It is not advisable to disable the check unless you're trying to debug something, since you can cause the server to hang. Generally if you have a loop so long it can cause the regular loop checks to freak out, you need to make a change to the loop behavior anyway.


map_format var (world)

See also:
icon_size var (world)
view var (world)
view var (client)
screen_loc var (movable atoms)
Topdown maps
Isometric maps
Side-view maps
Big icons
Tiled icons
Understanding the renderer
Default value:
TOPDOWN_MAP
Possible values:
  • TOPDOWN_MAP
  • ISOMETRIC_MAP
  • SIDE_MAP
  • TILED_ICON_MAP

This value says how the world will display maps. In a normal overhead tiled map the value is TOPDOWN_MAP for the top-down format. For older games that predate this feature, the value is TILED_ICON_MAP.

If you use a map format other than top-down, the HUD will still use a tile format like it would in top-down display. HUD objects are not projected into whatever map_format you use and they are not affected by changing client.dir. The size of the HUD is rounded up to the nearest number of full screen tiles; the size of each tile is defined by world.icon_size.

Top-down format

(See more at Topdown maps.)

This is the default map format. Icons are drawn in a tile form and viewed from overhead. In this layout, the layer assigned to each atom is very important. The number of tiles shown is set by client.view or world.view.

Because this format is familiar and easy to understand, it is the default setting. Most of the vars related to maps and atoms are designed and documented with this format in mind.

Tiled icon format

(See more at Tiled icons.) In BYOND 4.0 a new feature was introduced for using "big" icons, bigger than the standard tile size, by splitting them up into states like "0,0", "1,0", and so on. This functionality is no longer needed since BYOND now has the ability to display icons in their natural size. Some games that were designed before this, however, may still need to make use of this splitting feature that breaks icons into smaller tile-sized pieces. When an icon is broken into chunks, each state in the icon is given a thumbail version of the full image, and then new states are added to show each chunk. For instance if world.icon_size is the default 32×32, and the icon is 64×64, then the "door" state would become a thumbnail of the full door image while "door 0,0" (the lower left corner), "door 1,0", "door 0,1", and "door 1,1" were created to show each smaller section of the image. If the default "" state is broken into chunks, those chunks are just named "0,0" and so on without a space. This format is deprecated. It exists to support older games and allow them to be compiled without causing them to break, until they can be redesigned for one of the newer formats.

Isometric format

(See more at Isometric maps.)

If map_format is set to ISOMETRIC_MAP, the map is displayed in isometric form. Isometric tiles are displayed in a foreshortened diagonal perspective, where the "north" direction actually displays as northeast on the player's screen, and "east" shows up as southeast. The value of client.view or world.view is used to calculate the minimum number of tiles to display, and extra tiles to each side will be shown to fill in the corners.

In an isometric map, the tile width set in world.icon_size is the most important factor. This should be a multiple of 4 for best results. The minimum tile height is half that value, and any extra height is used to show vertical structures that "stick up" off the map surface. When you draw an isometric tile icon, start with a flattened diamond shape at the bottom that is only half as high as it is wide.

Isometric maps behave differently during drawing than top-down maps. In isometric, tiles that are nearer to the viewer's perspective are drawn in front of tiles farther back, regardless of layer. Layers only count within an individual tile. This means that if you want to have a vertical structure "stick up" to partially hide something behind it, the icon sticking up should always be on a tile forward from the one being partly covered. E.g. if you have a wall taking up part of your tile, it needs to be at the "back" end of the tile to properly hide anything on the tiles behind it.

The pixel_x and pixel_y values, step_x and step_y values, and the gliding that happens when moving between tiles, are based on the width set by world.icon_size. If you set world.icon_size="64x128" to show tall buildings, only the 64 matters for pixel offsets. Use pixel_w and pixel_z to adjust the position of atoms (or the client) horizontally or vertically without respect to client.dir or the map format.

Note: Offsets for x and y also affect the layering order used to draw the icons. Any object with a pixel offset onto another tile is considered part of whichever tile is closer.

If you use an icon wider than one tile, the "footprint" of the isometric icon (the actual map tiles it takes up) will always be a square. That is, if your normal tile size is 64 and you want to show a 128x128 icon, the icon is two tiles wide and so it will take up a 2×2-tile area on the map. The height of a big icon is irrelevant--any excess height beyond width/2 is used to show vertical features. To draw this icon properly, other tiles on that same ground will be moved behind it in the drawing order.

One important warning about using big icons in isometric mode is that you should only do this with dense atoms. If part of a big mob icon covers the same tile as a tall building for instance, the tall building is moved back and it could be partially covered by other turfs that are actually behind it. A mob walking onto a very large non-dense turf icon would experience similar irregularities.

Side-view format

(See more at Side-view maps.)

The SIDE_MAP format is like a cross between TOPDOWN_MAP and ISOMETRIC_MAP. It looks very similar to a top-down view but it is intended for more of a 3/4 perspective, where tiles lower on the screen are considered closer to the viewer. Because this impacts the way layers work, most of the layering behavior is the same as with isometric.

In a 3/4 perspective the tiles are often foreshortened, so pixel offsets are adjusted to account for this. For example, you may set world.icon_size to "32x24", but the tile is considered to be a perfect square if you look at it from the top down. Because the width is 32 pixels, the virtual height is also 32, so if you use pixel_y=32 the atom will appear one tile further back than it normally is. (This adjustment doesn't affect screen objects or pixel_w/pixel_z.)

Changing client.dir preserves the same tile size regardless of orientation.


map_cpu var (world)

See also:
cpu var (world)
tick_lag var (world)
tick_usage var (world)
Tick proc (world)

This is the percentage of a server tick that the server spends processing information about the map to send to players. A value of 0 would indicate very little cpu usage. A value of 100 would indicate full cpu usage, which means that the server cannot complete all the necessary computations during a tick to finish in time for the next tick. In this case, timed events (such as sleep) may take longer than requested.


maxx var (world)

See also:
area var (world)
maxy var (world)
maxz var (world)
turf var (world)
Map
Default value:
0

The world map is a three-dimensional block of turfs with coordinates ranging from (1,1,1) to (maxx,maxy,maxz). If set at compile time, it provides a lower bound and will be increased as needed by the map files.

The default value is 0, indicating no map. If any of the map dimensions are set to non-zero values at compile time, the others will default to 1.

New territory created by increasing the map boundaries is filled in with the default turf and area (world.turf, and world.area).


maxy var (world)

See also:
area var (world)
maxx var (world)
maxz var (world)
turf var (world)
Default value:
0

The world map is a three-dimensional block of turfs with coordinates ranging from (1,1,1) to (maxx,maxy,maxz). If set at compile time, it provides a lower bound and will be increased as needed by the map files.

The default value is 0, indicating no map. If any of the map dimensions are set to non-zero values at compile time, the others will default to 1.

New territory created by increasing the map boundaries is filled in with the default turf and area (world.turf, and world.area).


maxz var (world)

See also:
area var (world)
maxx var (world)
maxy var (world)
turf var (world)
Default value:
0

The world map is a three-dimensional block of turfs with coordinates ranging from (1,1,1) to (maxx,maxy,maxz). If set at compile time, it provides a lower bound and will be increased as needed by the map files.

The default value is 0, indicating no map. If any of the map dimensions are set to non-zero values at compile time, the others will default to 1.

New territory created by increasing the map boundaries is filled in with the default turf and area (world.turf, and world.area).


mob var (world)

See also:
New proc (client)
Default value:
/mob.

When a player connects to the world, the world is searched for a mob with the player's key. If one is found, the player is connected to that mob. If none is found, a new mob of type world.mob is created and the player is connected to this new mob.

The default value is /mob. Setting world.mob to 0 prevents the creation of default mobs.

Example:

world mob = /mob/newbie mob/newbie Login() src << "Welcome, [name]." ..()

This example will connect new players to mobs of type /mob/newbie. They are welcomed when they connect.


movement_mode var (world)

See also:
appearance_flags var (atom)
Enter proc (atom)
Exit proc (atom)
Cross proc (atom)
Uncross proc (atom)
Pixel movement
Gliding
Possible values:
LEGACY_MOVEMENT_MODE: Old BYOND behavior regarding pixel movement and turf contents (see below)
TILE_MOVEMENT_MODE: All atoms are locked to the tile grid
PIXEL_MOVEMENT_MODE: All movable atoms can use pixel movement unless otherwise specified (see below), but legacy behavior for turf contents is ignored
Default value:
LEGACY_MOVEMENT_MODE

Controls how movement works on the map.

TILE_MOVEMENT_MODE allows you to easily discard any and all pixel movement, so if step_x or step_y coordinates or unexpected atom bounds were loaded from a savefile, for instance, they would be eliminated. If you use any other movement mode, you can give an atom the TILE_MOVER flag and it will behave as if it were in this mode, while other atoms are free to do their own thing.

LEGACY_MOVEMENT_MODE exists to distinguish between old and new movement behavior. In older versions of BYOND before pixel movement, turfs took their contents into consideration by default in Enter() and Exit(). This doesn't really make sense for newer games, so in any other movement mode the turf behavior will ignore its contents. mob.Cross() is also affected, since it would return 0 by default in legacy mode when both mobs were dense; now by default it checks mob.group.


name var (world)

Default value:
The <world> part of the <world>.dmb file.

This is the name of the world.

Example:

world name = "The Void"

params var (world)

See also:
list associations
params2list proc
startup proc
Default value:
null

This is a list of parameters passed to the world from the command-line -params option when the server was started. The parameter text is passed through params2list() to generate the world.params list.

Example:

world/New() var/p if(params.len) world.log << "Command-line parameters:" for(p in params) world.log << "[p] = [params[p]]"

This example displays the value of each parameter.


port var (world)

See also:
OpenPort proc (world)
address var (world)
reachable var (world)
visibility var (world)

This is the network port of the world. If the world does not have an open network port, this is 0.


process var (world)

See also:
byond_version var (world)
system_type var (world)
shell proc

This read-only variable indicates the ID of the server's process on the system running it. The result is a number, unless for some unexpected reason the number won't fit in a num type, in which case it will be text. (In practice it should always be a number.)


realtime var (world)

See also:
time var (world)
timeofday var (world)
time2text proc

This is the time (in 1/10 seconds) since 00:00:00 GMT, January 1, 2000 (also known as the BYOND era).

Because this is a large number, BYOND's number system isn't capable of enough precision to deliver the exact number of 1/10 second ticks. It usually rounds off to the nearest several seconds. For more accurate readings use world.timeofday.


reachable var (world)

See also:
port var (world)
OpenPort proc (world)

Returns 1 if the world is currently hosted and the port can be reached by players (as determined by the BYOND hub), 0 if not.

If the port is not reachable, there may be a brief period during which the hub is still attempting to make contact; during that time the port is assumed to be reachable. Currently, the reachability test times out and fails after 30 seconds.


sleep_offline var (world)

Default value:
0

Setting this to 1 causes the world to be suspended when there are no players, even if you have sleeping procs waiting to happen. The default value is 0, which means the server will only sleep if there are no players and no procs waiting to happen. The main purpose of the variable is to save the cpu from doing work when there is nobody around to appreciate it. On the other hand, that doesn't give the poor NPC's a break from the nasty humans.


status var (world)

See also:
hub var (world)
game_state var (world)
visibility var (world)

This is a short text string used in BYOND hub to describe the state of a game in progress. For example, you might want to indicate if new players will be able to actively play, or whether they would have to join as spectators.

Example:

world status = "accepting players" mob/verb/start_game() world.status = "accepting spectators" //...

system_type var (world)

See also:
byond_version var (world)
process var (world)
shell proc

This variable indicates the operating system type at run-time. It will be one of the following constants:


tick_lag var (world)

See also:
fps var (world)
tick_lag var (client)
tick_usage var (world)
sleep proc
Default value:
1

This is the smallest unit of time (one server tick) measured in 1/10 seconds. The duration of events that take some finite amount of time (like sleep) will be rounded to a whole number of ticks.

Players are limited to one command (including movements) per server tick, so this value can be used to adjust the responsiveness of the game. If the network is too slow to keep up with players, their commands will get queued up, which can be annoying when trying to move. In this case, tick_lag should be increased so that the stored up movement commands are discarded. On the other hand, if you have a very fast network, you may wish to decrease tick_lag to speed up the response time to player commands.

Often it is more convenient to set world.fps instead of world.tick_lag, since fps (frames per second) is an easier way to think of server ticks. world.tick_lag is 10 / world.fps and vice-versa, so a tick_lag of 0.25 is equal to 40 fps.

If you set client.tick_lag or client.fps to a value other than 0, you can make the client tick at a different (usually faster) rate.


tick_usage var (world)

See also:
cpu var (world)
tick_lag var (world)
Tick proc (world)

This is the approximate percentage of the server tick that has been used already. A value under 100 means there's time to do more calculations, which can include any pending procs that are still waiting to run on this tick. When the value is over 100, the tick is running long and your world will experience lag.

Keep in mind that sending maps to clients is the last thing that happens during a tick, except for handling any events such as player commands that might arrive before the next tick begins. Therefore in a verb, tick_usage might have a higher value than you would expect to see in a proc that loops and sleeps.


time var (world)

See also:
realtime var (world)
tick_lag var (world)

This gives the amount of time (in 1/10 seconds) that the world has been running. In actual fact, it is the number of server ticks that have passed multiplied by world.tick_lag. Therefore if the server sleeps (when no players are connected) this time is not counted. Also, if the server runs overtime during a tick (because procs take longer than tick_lag to finish) this still only counts as one tick. This value is therefore a measure of "game time" rather than real time.


timeofday var (world)

See also:
realtime var (world)
time var (world)
time2text proc

This is the time (in 1/10 seconds) since 00:00:00 GMT today. It is basically identical to world.realtime but doesn't include any information about the date. This is a much smaller number; hence it is more accurate.


timezone var (world)

See also:
realtime var (world)
timeofday var (world)
timezone var (client)
time2text proc

This is the time offset from UTC, in hours, for the world's time zone. It can be used in the time2text() proc, although it is the default time zone for that proc.


turf var (world)

Default value:
/turf.

This is the default turf type to be placed on the map wherever no turf is specified. A value of 0 turns off the default turf.


url var (world)

See also:
address var (world)

This is the full network address of the world. (For example, byond://dan.byond.com:6005.)


version var (world)

See also:
hub var (world)
Default value:
0

If you are distributing your game to players, you can use this variable to automatically notify them of new releases. To do so, you will first need to set world.hub to the hub path of your game. You can then advertise the current version by configuring that value in your hub console.

When players boot up an outdated version of your game (as indicated by comparing world.version with the version advertised by BYOND hub), they will be notified of the new release.


view var (world)

See also:
lazy_eye var (client)
show_map var (client)
view proc
view var (client)
Default value:
5
Possible values:
-1 to 34 or "WIDTHxHEIGHT"

This is the default map viewport range. The default value of 5 produces an 11x11 viewport. A value of -1 turns off the map display altogether. The client may automatically scale down icons in order to conveniently fit the map on the player's screen.

For non-square views, you can assign this to a text string of the form "WIDTHxHEIGHT". For example, "11x11" is equivalent to a view depth of 5, but you could make it wider like this: "13x11".

This setting also affects the default range of the view(), oview(), range(), and orange() procedures.

If the entire map is small enough to fit on one screen (arbitrarily defined to be 21x21 or less), the default view is automatically adjusted to fit the map. In this case, client.lazy_eye is also automatically turned on by default, since you probably don't want the map to scroll around.


visibility var (world)

See also:
OpenPort proc (world)
hub var (world)
Default value:
1 (visible)

This controls whether the world advertises itself in the BYOND Hub when it has an open network port for accepting players. The visibility of the world still depends on whether any of the connected players has their location reporter turned on, and that in turn relies on the pager being turned on.


Special notes

This section of the reference should help explain some concepts that may be harder to understand or that can use more clarification.

Language features
Numbers
Regular expressions
Unicode
Icons
Big icons
Tiled icons
Map formats
Topdown maps
Isometric maps
Side-view maps
Movement
Gliding
Pixel movement
Display
Understanding the renderer
HUD / screen objects
Color matrix
Filter effects
Particle effects
Color gradient
Generators
Projection matrix
BACKGROUND_LAYER
EFFECTS_LAYER
TOPDOWN_LAYER

BACKGROUND_LAYER

See also:
layer var (atom)
plane var (atom)
map_format var (world)
EFFECTS_LAYER
TOPDOWN_LAYER
stddef.dm file
Understanding the renderer

This is mostly no longer needed. A negative value for plane is the preferred way to do show objects in the background. It can still be used however when you want to rearrange objects in the same plane when using PLANE_MASTER for visual effects.

BACKGROUND_LAYER is a special high value that can be added to the regular layer of any atom.

The purpose of this value is to make an atom appear below any regular atoms, even if they share the same plane. In an isometric map for instance, HUD objects will always appear above the map, but makeing a HUD object appear behind the map was basically impossible without this feature until plane was implemented.

When using this special layer, it should be added to the layer an atom normally uses. For instance an obj should have a layer of BACKGROUND_LAYER + OBJ_LAYER.

This can be mixed with TOPDOWN_LAYER and EFFECTS_LAYER, but it will take precedence over both. Anything with BACKGROUND_LAYER will always appear below anything without it on the same plane.

Images or overlays with FLOAT_LAYER can be left alone. They will automatically have the same layer as whatever atom they are attached to.


Big icons

See also:
icon
procs (icon)
Blend proc (icon)
map_format var (world)
icon_size var (world)
Tiled icons
Isometric maps
Side-view maps

BYOND allows you to use icons that are not the same size as the tile size defined in world.icon_size. These icons can be manipulated with the /icon datum using their raw, native size, and shown on the map in full size. To use the old behavior where an atom can display only an icon of the normal tile size, use the TILED_ICON_MAP value for map_format instead.

When you use an icon of non-standard size on an atom, the icon is "anchored" to the southwest corner of the atom. If you are using a top-down view (world.map_format=TOPDOWN_MAP), the icon will appear to spread out further to the east and north. In an isometric map (world.map_format=ISOMETRIC_MAP), the icon will cover additional tiles north and east as well. The "footprint" of an isometric icon--the actual map tiles it covers--is always square, so if your tile size is 64x64 and you use a 128x64 icon, the 128-pixel width means the icon will cover a 2x2 section of map tiles.

It is important to remember that using a big icon is a visual effect only. It will not affect how the atom bumps into other atoms or vice-versa.

Big icons will affect layering--the order in which icons are drawn. In general, because a big icon is covering more than one tile of the map, it will try to draw above any other tiles in that space that are on the same layer. This way, you can set a turf to use a big icon without having to change the turfs to the north and east. If an atom has a big icon, any overlays and underlays attached to it will be pulled forward as well, so they will draw in front of anything on their same layer. In isometric mode this is about the same, except that the layer isn't that important--anything in the way will just be moved back behind the big icon.

Note: Big overlays will not "pull forward" on their own. If the main atom uses a single-tile icon, a big overlay attached to it will not try to draw in front of other icons on the same layer. This is so that name labels, health bar overlays, etc. will not cause any odd behavior. To be safe, you should always specify a layer when adding an overlay.

In isometric mode, layering is affected by the "distance" between the atom and the viewer, so putting a regular-sized icon and part of a big icon on the same tile could cause layering oddities. Tiles that are covered by a big icon will tend to be drawn behind the big icon as mentioned above. For this reason, any atoms whose icons cover more than one tile (the extra height of an isometric icon doesn't count) should always be dense, and you should block movement onto any tile covered by them.

When manipulating icons with the /icon datum, you can still use Blend() to combine icons of different sizes. By default, the icons will be lined up at their southwest corners. You can change the position at which the second icon is blended.


Color gradient

See also:
gradient proc
color var (atom)
Particle effects
Color space

A color gradient is a special list that defines a range of colors that you can smoothly interpolate between. A simple example is a gradient from red to white:

Example:

list("red", "white") // OR list(0, "red", 1, "white")

Applying a number like 0.2 to this gradient would give you a color that's 20% of the way from red to white. More complex gradients however are also possible.

The format of a gradient is a list that contains a number (the position along the gradient, from 0 to 1 unless you use values outside that range) followed by a color. You can have as complex a gradient as you like. If you reuse the same number twice in a row, the gradient will have a sudden color change at that point.

It is also possible to skip numbers or colors, and they will be filled in automatically with the previous number or color. The exceptions are at the beginning and ends of the list; at the end of the gradient, the last color is assigned a number 1 by default, and the first is assigned 0. If you skip colors at the beginning, they will be filled in with the first color you use.

Include "loop" anywhere in the list to make this a looped gradient. If you don't, any numbers outside the gradient's range will be clamped to that range. E.g., in a normal gradient ranging from 0 to 1, a number of 1.2 is interpreted as 1 without a loop and 0.2 with a loop.

Here are some more examples:

Example:

// color wheel; ranges 0 to 6 and loops list(0, "#f00", 1, "#ff0", 2, "#0f0", 3, "#0ff", 4, "#00f", 5, "#f0f", 6, "#f00", "loop") // 10% each red, yellow, green, blue, with a 20% transition zone between each // notice no color follows 0.4 or 0.7, so the previous color is used list(0.1, "#f00", 0.3, "#ff0", 0.4, 0.6, "#008000", 0.7, 0.9, "#00f") // green and black stripes list(0.5, "#008000", 0.5, "#000000", "loop")

You can also include "space" in the list, and give it an associated value that describes the color space this gradient uses to interpolate between colors. For instance, "space"=COLORSPACE_HSL will use HSL interpolation instead of the default RGB. See Color space for more information.

Example:

// color wheel with a different color space list(0, "#f00", 3, "#0ff", 6, "#f00", "loop", "space"=COLORSPACE_HSLA)

Currently, color gradients are only used by particle effects and the gradient proc. With particles, if you use a gradient the particle's color is given as a number, and that number is used to look up its real color from the gradient. The number can change over time, thus changing the particle's color.


Color matrix

See also:
color var (atom)
color var (client)
MapColors proc (icon)

A color matrix is used to transform colors, in the same way that a matrix represented by the /matrix datum is used to transform 2D coordinates. A transformation matrix is 3x3, of which only 6 values are needed because the last column is always the same. A color matrix, because it transforms four different numbers instead of two, is 5x5.

                |rr rg rb ra 0|
                |gr gg gb ga 0|
[r g b a 255] x |br bg bb ba 0| = [r' g' b' a' 255]
                |ar ag ab aa 0|
                |cr cg cb ca 1|

In easier-to-understand terms, this is how the result is calculated:

new_red = red * rr + green * gr + blue * br + alpha * ar + 255 * cr new_green = red * rg + green * gg + blue * bg + alpha * ag + 255 * cg new_blue = red * rb + green * gb + blue * bb + alpha * ab + 255 * cb new_alpha = red * ra + green * ga + blue * ba + alpha * aa + 255 * ca

It is helpful to think of each row in the matrix as what each component of the original color will become. The first row of the matrix is the rgba value you'll get for each unit of red; the second is what each green becomes, and so on.

Because the fifth column of the matrix is always the same, only 20 of the values need to be provided. You can use a color matrix with atom.color or client.color in any of the following ways:

RGB-only (9 to 12 values)
list(rr,rg,rb, gr,gg,gb, br,bg,bb, cr,cg,cb)
RGBA (16 to 20 values)
list(rr,rg,rb,ra, gr,gg,gb,ga, br,bg,bb,ba, ar,ag,ab,aa, cr,cg,cb,ca)
Row-by-row (3 to 5 rgb() values, or null to use the default row)
list(red_row, green_row, blue_row, alpha_row, constant_row)

Reading a color var that has been set to a matrix will return the full 20-item list, where every 4 items represent a row in the matrix (without the fifth column).

In the MapColors() icon proc, the values are sent as arguments, not as a list.


EFFECTS_LAYER

See also:
layer var (atom)
plane var (atom)
map_format var (world)
BACKGROUND_LAYER
TOPDOWN_LAYER
stddef.dm file
Understanding the renderer

This is mostly no longer needed. A negative value for plane is the preferred way to do show objects in the background. It can still be used however when you want to rearrange objects in the same plane when using PLANE_MASTER for visual effects.

EFFECTS_LAYER is a special high value that can be added to the regular layer of any atom.

The purpose of this value is to make an atom appear above any regular atoms. For instance, in an isometric map if you want to display a character's name below them, it does not make much sense to have nearer objects cover up that name, so you can tell the name overlay to use EFFECTS_LAYER + MOB_LAYER and it will show up on top of all the normal icons on the map. This has been somewhat obviated by plane but may still be useful in some cases.

When using this special layer, it should be added to the layer an atom normally uses. For instance an obj should have a layer of EFFECTS_LAYER + OBJ_LAYER.

This can be mixed with TOPDOWN_LAYER, in non-topdown map formats. Anything in TOPDOWN_LAYER will display on top of EFFECTS_LAYER, and TOPDOWN_LAYER + EFFECTS_LAYER will be above both.

This can also be mixed with BACKGROUND_LAYER, which takes priority over everything else.

Images or overlays with FLOAT_LAYER can be left alone. They will automatically have the same layer as whatever atom they are attached to.


Filter effects

See also:
filters var (atom)
appearance_flags var (atom)
filter proc
animate proc
Understanding the renderer

Filters are a way of adding special effects to an icon, or a group of icons (see KEEP_TOGETHER in appearance_flags), by post-processing the image. A filter object describes a specific form of image processing, like for instance a blur or a drop shadow. Filters can be added or removed at will, and can even be animated.

A filter is created by using the filter proc like so:

// halo effect mob.filters += filter(type="drop_shadow", x=0, y=0,\ size=5, offset=2, color=rgb(255,255,170))

These are the filters currently supported:


Alpha mask filter

See also:
icon var (atom)
render_target var (atom)
Format:
filter(type="alpha", ...)
Args:
x: Horizontal offset of mask (defaults to 0)
y: Vertical offset of mask (defaults to 0)
icon: Icon to use as a mask
render_source: render_target to use as a mask
flags: Defaults to 0; use see below for other flags

Uses an icon or render target as a mask over this image. Every pixel that is transparent in either the image or the mask, is transparent in the result.

The x and y values can move the mask from its normal position. By default, the mask is centered over the center of the image.

The MASK_INVERSE flag will invert the alpha mask so that opaque areas in the mask become transparent, and vice-versa. There is also a MASK_SWAP flag which treats the source image as the mask and vice-versa, which might be useful for some effects.

Note: Unlike many other filters, this filter is taken into account for mouse-hit purposes.


Angular blur filter

See also:
Gaussian blur (filters)
Radial blur (filters)
Motion blur (filters)
Format:
filter(type="angular_blur", ...)
Args:
x: Horizontal center of effect, in pixels, relative to image center
y: Vertical center of effect, in pixels, relative to image center
size: Amount of blur (defaults to 1)

Blurs the image by a certain amount in a circular formation, as if the image is spinning. The size of the blur can roughly be thought of in "degrees" worth of blur. As the distance from the center increases, the blur becomes more noticeable since the same amount of angular motion has to travel farther along a circle.

Typically this blur is used with an entire plane, but it could be used to give a sense of motion blur to a spinning object.

Note: Large blurs will look worse toward the edges due to limited sampling. Loss of accuracy will appear where size × distance is greater than about 300. You can increase accuracy by breaking up large sizes into multiple filter passes with differing sizes. The blur used is Gaussian, so combining blur sizes A and B will give a total size of sqrt(A2+B2).


Bloom filter

See also:
Gaussian blur (filters)
Drop shadow (filters)
Format:
filter(type="bloom", ...)
Args:
threshold: Color threshold for bloom
size: Blur radius of bloom effect (see Gaussian blur)
offset: Growth/outline radius of bloom effect before blur
alpha: Opacity of effect (default is 255, max opacity)

Post-processing effect that makes bright colors look like they're a strong light source, spreading their light additively to other nearby pixels. This is a complex effect that involves multiple shader passes. For both performance and visual reasons, it is usually best applied to an entire plane rather than to individual objects.

The color threshold determines which pixels this effect applies to. If any of the red, green, or blue components of the pixel are greater than the same component for the threshold, that pixel will bloom. The blooming pixels then have their colors spread outward to create a glow that gets added to the original image.

The offset and size parameters are used to control the glow effect. They work the same as they do in the drop shadow filter: offset causes the light to grow outwards, and a blur of size is then applied to soften it. Often just using a blur alone will produce a pleasing effect. By playing with these two values you can make the bloom effect appear differently.

The alpha value is applied to any light contributions from bloomed pixels that get added to the original image, so values lower than 255 can make the effect less pronounced. This can be very useful if you choose to animate the filter.


Gaussian blur filter

See also:
Motion blur (filters)
Radial blur (filters)
Angular blur (filters)
Drop shadow (filters)
Format:
filter(type="blur", ...)
Args:
size: Amount of blur (defaults to 1)

Blurs the image by a certain amount. The size of the blur can roughly be thought of in "pixels" worth of blur.

Note: Large blurs will result in reduced performance. The highest size that can be handled easily in this filter is 6. Higher sizes require multiple passes, although the filter will "cheat" and use low-quality passes for much higher sizes.


Color matrix filter

See also:
color var (atom)
Color matrix
Color space
Format:
filter(type="color", ...)
Args:
color: A color matrix
space: Value indicating color space: defaults to FILTER_COLOR_RGB

Applies a color matrix to this image. Unlike with the atom.color var, you can apply color conversions other than the regular RGBA color space, depending on the value of space. See Color space for more information.


Displacement map filter

See also:
Alpha mask (filters)
icon var (atom)
render_target var (atom)
Format:
filter(type="displace", ...)
Args:
x: Horizontal offset of map (defaults to 0)
y: Vertical offset of map (defaults to 0)
size: Maximum distortion, in pixels
icon: Icon to use as a displacement map
render_source: render_target to use as a displacement map

Uses an icon or render target as a template for various warping effects on the main image.

In the displacement map, pixels that have a higher red component will make the image appear to warp to the left, lower reds warp it to the right, and gray (r=128) will cause no horizontal warping. The green component affects the vertical: higher to warp upward, lower to warp downward. Transparent pixels in the displacement map will have no effect.

This can be used for very complex distortion, unlike other distortion filters such as wave and ripple that are confined to specific equations.


Drop shadow filter

See also:
Gaussian blur (filters)
Outline (filters)
Format:
filter(type="drop_shadow", ...)
Args:
x: Shadow horizontal offset (defaults to 1)
y: Shadow horizontal offset (defaults to -1)
size: Blur amount (defaults to 1; negative values create inset shadows)
offset: Size increase before blur (defaults to 0)
color: Shadow color (defaults to 50% transparent black)

Applies a drop shadow to this image. This is a combination of multiple filters, since it will apply an outline if offset is included, a Gaussian blur to the shadow, and will underlay the shadow beneath the image.

You can also think of this filter as an outer glow.

If you use a size less than 0, the shadow will appear inside the image instead. This would be an inset shadow, or inner glow.


Layering (composite) filter

See also:
icon var (atom)
render_target var (atom)
Format:
filter(type="layer", ...)
Args:
x: Horizontal offset of second image (defaults to 0)
y: Vertical offset of second image (defaults to 0)
icon: Icon to use as a second image
render_source: render_target to use as a second image
flags: FILTER_OVERLAY (default) or FILTER_UNDERLAY
color: Color or color matrix to apply to second image
transform: Transform to apply to second image
blend_mode: Blend mode to apply to the top image

Composites another image over or under this image. Using the FILTER_OVERLAY flag, which is the default, puts the second image on top of what's already here. FILTER_UNDERLAY puts it underneath.

The x and y values can move the mask from its normal position. By default, the second image is centered over the center of the first.

The color, transform, and blend_mode vars are available for convenience. Because the bottom image is drawn over a blank background, blend_mode is always applied to the top image. All of the other vars apply to the second image being drawn.

Note: Transforms use default bilinear scaling, since PIXEL_SCALE is not available here.

Note: Like most other filters, this filter is not taken into account for mouse-hit purposes. Any layered icons will be strictly visual.


Motion blur filter

See also:
filters var (atom)
Gaussian blur (filters)
Format:
filter(type="motion_blur", ...)
Args:
x: Blur vector on the X axis (defaults to 0)
y: Blur vector on the Y axis (defaults to 0)

Applies Gaussian blur in one direction only. The amount and direction are both specified by x and y. The size of the blur is equal to sqrt(x*x + y*y).

See Gaussian blur for more information.


Outline filter

See also:
Drop shadow (filters)
Format:
filter(type="outline", ...)
Args:
size: Width in pixels (defaults to 1)
color: Outline color (defaults to black)
flags: Defaults to 0 (see below)

Applies an outline to this image.

At larger sizes, the outline is less accurate and will take more passes to produce. Performance and appearance are best at sizes close to 1 or less.

flags can be a combination of the following values:

0
Ordinary outline
OUTLINE_SHARP
Avoid antialiasing in the outline
OUTLINE_SQUARE
Extend the outline sharply from corner pixels; for a box this will maintain a box shape without rounded corners

Radial blur filter

See also:
Gaussian blur (filters)
Angular blur (filters)
Motion blur (filters)
Format:
filter(type="radial_blur", ...)
Args:
x: Horizontal center of effect, in pixels, relative to image center
y: Vertical center of effect, in pixels, relative to image center
size: Amount of blur per pixel of distance (defaults to 0.01)

Blurs the image by a certain amount outward from the center, as if the image is zooming in or out. As the distance from the center increases, the amount of blurring increases, and near the center the blur is hardly visible at all. The size value is smaller by default for this filter than it is for other filters, since it's typically used with an entire plane where the distance from the center can easily be several hundred pixels.

Typically this blur is used with an entire plane.

Note: Large blurs will look worse toward the edges due to limited sampling. Loss of accuracy will begin when size × distance is greather than 6. You can increase accuracy by breaking up large sizes into multiple filter passes. The blur used is Gaussian, so combining blur sizes A and B will give a total size of sqrt(A2+B2).


Rays filter

Format:
filter(type="rays", ...)
Args:
x: Horiztonal position of ray center, relative to image center (defaults to 0)
y: Vertical position of ray center, relative to image center (defaults to 0)
size: Maximum length of rays (defaults to 1/2 tile width)
color: Ray color (defaults to white)
offset: "Time" offset of rays (defaults to 0, repeats after 1000)
density: Higher values mean more, narrower rays (defaults to 10, must be whole number)
threshold: Low-end cutoff for ray strength (defaults to 0.5, can be 0 to 1)
factor: How much ray strength is related to ray length (defaults to 0, can be 0 to 1)
flags: Defaults to FILTER_OVERLAY | FILTER_UNDERLAY (see below)

Draws random rays that radiate outward from a center point. (That point may be outside of the image.) As they move outward, their alpha value diminishes linearly. These are meant to be animated. The offset value determines the "time", where every jump of +1 can be a very different set of rays, and every 1000 units this filter will repeat.

The threshold value can be thought of as a way of culling lower-strength rays. Ray strength is anywhere from 0 to 1 at any given angle, but values below threshold may as well be 0. Values above that are re-scaled into a range of 0 to 1.

The factor parameter allows you to tie the ray's length to its strength. At 0, the length of every ray is the same. At 1, the length ranges from 0 to size. Generally speaking, the higher factor is, the more the rays will appear to move outward as they strengthen and inward as they weaken.

Ray color can be provided as a matrix. Only the diagonal values of the color matrix will be used, but using a matrix will allow you to set values outside of the normal color range.

flags can have the following values:

0
The rays are drawn alone, erasing the existing image (useful for some effects).
FILTER_OVERLAY
The rays are overlaid on top of the existing image.
FILTER_UNDERLAY
The rays are drawn underneath the existing image.
FILTER_OVERLAY | FILTER_UNDERLAY
Default. For plane masters, this will use the FILTER_OVERLAY behavior and draw the rays over the plane, and for all other images it will default to FILTER_UNDERLAY to draw the rays beneath them.

Ripple filter

See also:
Wave (filters)
Format:
filter(type="ripple", ...)
Args:
x: Horiztonal position of ripple center, relative to image center (defaults to 0)
y: Vertical position of ripple center, relative to image center (defaults to 0)
size: Maximum distortion in pixels (defaults to 1)
repeat: Wave period, in pixels (defaults to 2)
radius: Outer radius of ripple, in pixels (defaults to 0)
falloff: How quickly ripples lose strength away from the outer edge (defaults to 1)
flags: Defaults to 0; use WAVE_BOUNDED to keep distortion within the image

Applies a ripple distortion effect to this image.

This filter is meant to be animated. A good animation will typically start at a radius of 0 and animate to a larger value, with size decreasing to 0.

The falloff parameter can be tweaked to your liking. A value of 1 should look reasonably like ripples in water, with the inner ripples losing strength. A value of 0 will cause no reduction in strength.

The equation governing the ripple distortion is size × sin(2πr') ÷ (2.5 × falloff × r'2 + 1), where r' = (radius - distance) ÷ repeat.

Up to 10 ripples can be stacked together in a single pass of the filter, as long as they have the same repeat, falloff, and flags values. (See the wave filter for the WAVE_BOUNDED flag.)


Wave filter

See also:
Ripple (filters)
Format:
filter(type="wave", ...)
Args:
x: Horiztonal direction and period of wave
y: Vertical direction and period of wave
size: Maximum distortion in pixels (defaults to 1)
offset: Phase of wave, in periods (e.g., 0 to 1)
flags: Defaults to 0; see below for other flags

Applies a wave distortion effect to this image.

The x and y parameters specify both the direction and period of the wave; the period is sqrt(x*x + y*y).

This filter is meant to be animated, from whatever offset you want to offset+1, and then repeating. With multiple waves, you can produce a very convincing water effect.

Example

#define WAVE_COUNT 7 atom/proc/WaterEffect() var/start = filters.len var/X,Y,rsq,i,f for(i=1, i<=WAVE_COUNT, ++i) // choose a wave with a random direction and a period between 10 and 30 pixels do X = 60*rand() - 30 Y = 60*rand() - 30 rsq = X*X + Y*Y while(rsq<100 || rsq>900) // keep trying if we don't like the numbers // keep distortion (size) small, from 0.5 to 3 pixels // choose a random phase (offset) filters += filter(type="wave", x=X, y=Y, size=rand()*2.5+0.5, offset=rand()) for(i=1, i<=WAVE_COUNT, ++i) // animate phase of each wave from its original phase to phase-1 and then reset; // this moves the wave forward in the X,Y direction f = filters[start+i] animate(f, offset=f:offset, time=0, loop=-1, flags=ANIMATION_PARALLEL) animate(offset=f:offset-1, time=rand()*20+10)

The equation governing the wave distortion is size × sin(2π(d - offset)), where d is the number of wave periods' distance from the center along the x, y direction.

The WAVE_SIDEWAYS flag will cause the distortion to be transverse (perpendicular) to the wave instead of in the same direction as the wave. The WAVE_BOUNDED flag limits the distortion to the confines of this image, instead of lettings its pixels spill out a little further from the distortion (and likewise, transparent pixels spill inward).

Up to 10 waves can be stacked together in a single pass of the filter, as long as they have the same WAVE_BOUNDED flags.


Generators

See also:
Particle effects
generator proc
color var (atom)
Color matrix

A generator is an object that can produce a random number, vector (list of 3 numbers), color (as a text string), or color matrix (list of 20 numbers) in a specified range according to rules you set down. It is used primarily for particle effects, since it can run on the client.

There are several types of generators:

Generators can also be chained together with math operators and some procs. The second value can be a regular value instead of a generator, so for instance you can multiply a vector by 2, or by a matrix to transform it.

OperatorsAction
+ - * /Arithmetic operators. You can multiply a 3D vector by a color matrix (where red,green,blue in the matrix correspond to x,y,z) to do a 3D transform, or by a 2D matrix for a 2D transform.
- (unary)Negate the value, same as multiplying by -1.
turn(), generator.Turn()Rotate a vector clockwise in the XY plane.

Gliding

See also:
Pixel movement
animate_movement var (movable atom)
appearance_flags var (atom)
glide_size var (movable atom)
bound_x var (movable atom)
bound_y var (movable atom)
bound_width var (movable atom)
bound_height var (movable atom)
step_size var (movable atom)
step_x var (movable atom)
step_y var (movable atom)
movement_mode var (world)
fps var (client)

Gliding is a "glitz" effect applied by BYOND to cover up the visual sins of tile-based movement, by making objects and the map appear to move smoothly from one tile to another instead of immediately jumping. It is also available to smooth over small jumps in pixel movement that might occur, for instance if the client FPS is set higher than the server's.

To control the gliding speed of an atom, set glide_size to the value of your choice. If this is not set, the client will attempt to adjust the speed manually. glide_size is measured in server ticks, so if client.fps is set to a value greater than world.fps, it will be scaled appropriately.

Whether an object glides or jumps is based on how far it moves relative to its step_size value, which by default is a full tile width. If the movement goes too far past step_size in the X or Y directions, it's no longer a glide.

The animate_movement var can be used to control the way in which an object glides, or suppress gliding altogether.

By using the LONG_GLIDE flag in appearance_flags, a diagonal glide will take just as long as a cardinal-direction glide by moving a fullt glide_size pixels in the dominant X or Y direction. Otherwise, gliding tries to move by that many pixels in strict Euclidean distance (a straight line) and diagonal glides take longer.

In LEGACY_MOVEMENT_MODE, gliding is turned off if you set any of the bound or step vars for an atom to a non-default value. The only gliding that occurs in this case is when client.fps is higher than world.fps. All other movement modes base gliding on an atom's glide_size value.


HUD / screen objects

See also:
screen_loc var (movable atoms)
screen var (client)
view var (client)
map_format var (world)
icon_size var (world)
layer var (atom)
image objects

HUD stands for Heads-Up Display, and refers to any atoms that appear on the screen but don't move when the player moves. These are also called screen objects. Any movable atom can be added to the HUD by setting its screen_loc var, and adding it to client.screen for each user who is supposed to see it. This can be used to display a character's vital stats, scores, etc.

If you want to have something like a health meter or name attached to a moving atom, use overlays or /image objects instead. An /image object is similar to a screen object in that it can be shown to only certain players instead of being shown to everyone.

The size of the screen depends on client.view (or world.view), world.map_format, and world.icon_size. In a normal topdown map format, client.view is the same as the screen size; in other map formats the screen might be a different size.

The screen_loc var can be set to a value like "1,1" (the southwest tile of the screen), "4,NORTH" (fourth tile from the west, along the north side of the screen), "SOUTHEAST", and so on. You can also include pixel offsets, percentages, and specify two corners to tile an icon repeatedly from one end to the other. See screen_loc for more details.

screen_loc can also be used to stretch the bounds of the HUD. A value of "0,0" will cause the atom to appear to the southwest of the southwest-most tile on the visible map, outside of the regular map bounds. Using HUDs in this way, you can provide a nice decorative "frame" for your map.

More complex

You can use HUDs in other map controls as well, by preceding screen_loc with the name of the map you will use followed by a colon. For instance, screen_loc="map2:1,1" will show an icon in the southwest corner of the map2 control. The actual size of a secondary HUD is based on how far out the icons in it extend in any direction. If you have one icon at "map2:1,1" and another at "map2:4,3", then that HUD will be four tiles wide and three high.


Isometric maps

See also:
map_format var (world)
icon_size var (world)
dir var (client)
pixel_w var (atom)
pixel_z var (atom)
screen_loc var (movable atoms)
Big icons
Side-view maps
Topdown maps
HUD
BACKGROUND_LAYER
EFFECTS_LAYER
TOPDOWN_LAYER

Isometric projection is a form of pseudo-3D in which the 2D icons used by BYOND can be arranged in a way to give the appearance of three dimensions. If you look at a map top-down, each tile on the map is a square. The map is rotated 45° clockwise and then tilted at an angle (30°) so that each square now looks like a foreshortened diamond from the viewer's perspective. What was once north now points to the northeast end of the viewer's screen; what was once east now points southeast to the viewer. Tiles that are more to the south or east are "nearer" to the viewer, and tiles that are north or west are "farther". The actual direction the map faces can be changed by using client.dir.

It is important to remember that this is an illusion of 3D, not real 3D.

To use isometric mapping, set world.map_format to ISOMETRIC_MAP. You should set world.icon_size so the tile width is a multiple of 4 pixels. The width of the tile is highly important. The height of your tiles should be at least half that value. BYOND uses a 2:1 isometric format, meaning that the diamond base of each tile is half as high as its width. For example if you have a 64x64 tile size, every diamond in the map will be 64 pixels wide by 32 high, and you have an extra 32 pixels at the top of your icon for vertical projections like buildings. If you set the tile size to 64x80, the base is still a 64x32 diamond and you have 48 pixels left over for vertical structures.

In this mode pixel_x and pixel_y will offset icons along the "ground". To adjust horizontal and vertical positions, use the pixel_w and pixel_z vars.

Layers

The layer var behaves differently in isometric mode. Because some tiles are nearer to the viewer than others, the tiles that are farther back need to be drawn first so they are behind any tiles that should go in front of them. So in isometric mode, the back row of tiles (a diagonal line of them) is drawn first, followed by the next row forward, and so on. The layer var only matters when icons overlap each other in the "physical" space, like an obj sitting on a turf.

When pixel or step offsets, or gliding, place an object on multiple turfs, it is drawn on top of the nearer turf (assuming its layer is higher).

Using icons wider than the regular tile size can have an impact on layering as well. See Big icons for more information.

Because of the order in which icons are drawn, you may want to limit the ability of an atom to cut diagonally around corners. While moving northeast behind a dense wall, for instance, a mob might temporarily appear in front of the wall because its pixel offsets (from gliding) temporarily put it on the same tile as the wall. If you do not want to limit corner-cutting, a simple workaround for this case is to give the wall a higher layer than the mob.

Screen objects (in client.screen) are always drawn on top of all isometric tiles, as is the case in other map modes as well.

Since it may be desirable in some games to use a topdown map for some situations (like a special battle map), you can add TOPDOWN_LAYER to any atom's layer—e.g., TOPDOWN_LAYER+TURF_LAYER—to make it appear in topdown mode. Topdown and isometric tiles really aren't meant to be mixed, but if they do mix you'll see topdown tiles always display above isometric tiles, just like screen objects do. The best way to use this is to apply TOPDOWN_LAYER to every tile in a certain part of the map that the players can't walk to.

If you want to use an overlay that should not be covered by other "nearer" icons on the map, such as a name or health meter, you can add EFFECTS_LAYER to the overlay's layer. Icons with EFFECTS_LAYER will draw above regular icons. Then objects with TOPDOWN_LAYER will draw on top of everything else. However, be aware that EFFECTS_LAYER has largely been superseded by the plane var.

Screen size

In this mode, world.view or client.view is used to define the minimum number of map tiles you will see, not the screen/HUD size which is calculated from client.view. Extra map tiles are shown to fill out the screen size. HUD objects use screen coordinates, so 1,1 is still the lower left.

The actual HUD size is always a full number of tiles, whose size is defined by world.icon_size. If you have a tile size of 64x64, and world.view=6 (a 13x13 map), a full 13x13 diamond of map tiles will be shown. The width of this diamond is 13 tiles. The height is only half that, plus whatever vertical space is needed to show the icons in that area. Then everything is rounded up to a full tile size, so the result is a 13x7-tile screen. This is the formula you need if you want to calculate the screen size:

pixel_width = round(icon_width * (view_width + view_height) / 2) pixel_height = round(icon_width * (view_width + view_height - 2) / 4) + icon_height screen_width = round((pixel_width + icon_width - 1) / icon_width) screen_height = round((pixel_height + icon_height - 1) / icon_height)

If you use TOPDOWN_LAYER, any topdown sections of the map will be limited to this same view.


Numbers

In DM, all numbers are stored in floating point format. Specifically, single-precision (32-bit) floating point. This is important to know if you think you will be working with large numbers or decimal values a lot, because the accuracy of the numbers is limited.

32-bit floating point numbers can represent integers from -16777216 to 16777216 (224). Non-integer values can get about as small as 2-126 and as large as 2127.

Floating point numbers do not handle most decimal values precisely. For instance, 0.1 is not exactly 0.1, because floating point numbers are stored in a binary format and in binary, 1/10 is a fraction that repeats forever—the same way 1/3 repeats as 0.33333... in decimal numbers. It ends up being rounded off, either a little higher or a littler lower than its true value. This means that the following loop won't work like you might expect:

Example:

for(i = 0, i < 100, i += 0.1) world << i

You might expect that code to loop exactly 1000 times, with i going from 0 up to 99.9 before stopping. The truth is more complicated, because 0.1 stored in floating point is actually greater than the exact value of 0.1. Other values might be more or less than their exact numbers, and as you add these numbers together repeatedly you'll introduce more and more rounding error.

Even more insidious, if you add 0.1 a bunch of times starting from 0, and then subtract it out again the same number of times, the result you get may not be 0. This is counterintuitive, because you might expect rounding errors to reverse themselves in the same order they crept in. Unfortunately it doesn't work that way.

You can correct for rounding error somewhat by using the round proc to adjust the loop var each time, although for performance reasons it might be preferable to find another alternative.

for(i = 0, i < 100, i = round(i + 0.1, 0.1)) world << i

Only fractions whose denominators are powers of 2 are immune to this rounding error, so 0.5 is in fact stored as an exact value.

Another place floating point may lose accuracy is when you try to add numbers of very different sizes. For instance as stated above, the upper limit for accurate integers is 16777216. If you try to use a number such as 100 million it will only be approximate, so adding 1 to that number won't actually change it because the 1 is so much smaller, it will be gobbled up by rounding error.

Also for the same reasons stated above, division will cost you accuracy. Again you can divide by powers of 2 easily enough, and you can divide an integer by any of its factors (like dividing 9 by 3) without a problem, but a fraction like 1/3 will repeat forever so it gets rounded to as much precision as floating point can manage.

In decimal, floating point numbers have at least six decimal digits of precision. Since they're actually stored in binary, their true precision is exactly 24 bits.


Particle effects

See also:
particles (movable atom var)
Generators
generator proc
Projection matrix
stddef.dm file

A particle set is a special effect, whose computations are handled entirely on the client, that spawns and tracks multiple pixels or icons with a temporary lifespan. Examples of this might be confetti, sparks, rocket exhaust, or rain or snow. Particles are rendered on a special surface and that gets attached to an obj or a mob like an overlay.

Particles can exist in 3 dimensions instead of the usual 2, so a particle's position, velocity, and other values may have a z coordinate. To make use of this z coordinate, you can use a projection matrix. (The value of the z coordinate must be between -100 and 100 after projection. Otherwise it's not guaranteed the particle will be displayed.)

To create a particle set, use new to create a new /particles datum, and then you can set the datum's vars. The vars can be set to constant values, or generator functions that will allow the client to choose from a range of values when spawning those particles. (The easiest way to handle this is to create your own type that inherits from /particles, and set up the parameters you'll want at compile-time.)

After the datum is created, it can be assigned to an obj or mob using their particles var. The particles will appear on the map wherever that obj or mob appears.

Example:

particles/snow width = 500 // 500 x 500 image to cover a moderately sized map height = 500 count = 2500 // 2500 particles spawning = 12 // 12 new particles per 0.1s bound1 = list(-1000, -300, -1000) // end particles at Y=-300 lifespan = 600 // live for 60s max fade = 50 // fade out over the last 5s if still on screen // spawn within a certain x,y,z space position = generator("box", list(-300,250,0), list(300,300,50)) // control how the snow falls gravity = list(0, -1) friction = 0.3 // shed 30% of velocity and drift every 0.1s drift = generator("sphere", 0, 2) obj/snow screen_loc = "CENTER" particles = new/particles/snow mob proc/CreateSnow() client?.screen += new/obj/snow

These are the vars that can be used in a particle set. "Tick" refers to a BYOND standard tick of 0.1s.

Particle vars that affect the entire set (generators are not allowed for these)
VarTypeDescription
widthnumSize of particle image in pixels
height
countnumMaximum particle count
spawningnumNumber of particles to spawn per tick (can be fractional)
bound1vectorMinimum particle position in x,y,z space; defaults to list(-1000,-1000,-1000)
bound2vectorMaximum particle position in x,y,z space; defaults to list(1000,1000,1000)
gravityvectorConstant acceleration applied to all particles in this set (pixels per squared tick)
gradientcolor gradientColor gradient used, if any
transformmatrixTransform done to all particles, if any (can be higher than 2D)
Vars that apply when a particle spawns
lifespannumMaximum life of the particle, in ticks
fadenumFade-out time at end of lifespan, in ticks
fadeinnumFade-in time, in ticks
iconiconIcon to use, if any; no icon means this particle will be a dot
Can be assigned a weighted list of icon files, to choose an icon at random
icon_statetextIcon state to use, if any
Can be assigned a weighted list of strings, to choose an icon at random
colornum or colorParticle color (not a color matrix); can be a number if a gradient is used
color_changenumColor change per tick; only applies if gradient is used
positionnumx,y,z position, from center in pixels
velocitynumx,y,z velocity, in pixels
scalevector (2D)Scale applied to icon, if used; defaults to list(1,1)
grownumChange in scale per tick; defaults to list(0,0)
rotationnumAngle of rotation (clockwise); applies only if using an icon
spinnumChange in rotation per tick
frictionnumAmount of velocity to shed (0 to 1) per tick, also applied to acceleration from drift
Vars that are evalulated every tick
driftvectorAdded acceleration every tick; e.g. a circle or sphere generator can be applied to produce snow or ember effects

The icon and icon_state values are special in that they can't be assigned a generator, but they can be assigned a constant icon or string, respectively, or a list of possible values to choose from like so:

icon = list('confetti.dmi'=5, 'coin.dmi'=1)

The list used can either be a simple list, or it can contain weights as shown above.

Changing a var on a particle datum will make changes to future particles. For instance, you can set the datum's spawning var to 0 to make it stop creating new particles. (Note: If you are changing a vector or color matrix, such as gravity, you need to assign a new value. You can't for instance set particles.gravity[2] = 0 because it won't do anything to update the particle stream.)

The same particle datum can be assigned to more than one movable atom. However the particles displayed by each atom will be different.


Pixel movement

See also:
Bounding boxes
bound_x var (movable atom)
bound_y var (movable atom)
bound_width var (movable atom)
bound_height var (movable atom)
Speed and position
step_size var (movable atom)
step_x var (movable atom)
step_y var (movable atom)
locs list var (movable atom)
contents list var (atom)
fps var (world)
Movement
Move proc (movable atom)
Cross proc (atom)
Crossed proc (atom)
Uncross proc (atom)
Uncrossed proc (atom)
movement_mode var (world)
appearance_flags var (atom)
Other topics
bounds proc
bounds_dist proc
Gliding

Pixel movement is a concept that allows atoms to escape the constraints of BYOND's historically tile-based movement, and move in smaller steps. In the past this had to be done with soft code, but that was sometimes inconvenient and it did not perform as well in projects with many objects moving.

The key to understanding pixel movement is to use the bound and step vars. You use the bound family of vars to define a bounding box for a movable atom, instead of just making it one full tile in size. The step vars can give it a movement speed and offset it from the corner of the tile it's standing on.

Those are for movable atoms only; they do not apply to turfs.

If world.movement_mode is set to TILED_MOVEMENT_MODE, all movable atoms must be aligned to the tile grid: their step_x/y/size values must be multiples of the icon size, and their bounds must also land on tile boundaries although the atom can be bigger than one tile. In other movement modes you can specify that only specific atoms use this behavior, by giving them the TILE_MOVER appearance flag.

Bounding boxes

As an example, if your players' mobs have icons that only cover the center 24×24 pixels of a regular 32×32 icon, then you would set the mobs' bound_x and bound_y to 4--because there are 4 pixels unused to the left and bottom--and bound_width and bound_height to 24.

The mob's physical location on the map depends on four things: Its loc, its step_x/y values, its bound_x/y values, and its bound_width/height. The lower left corner of the bounding box, relative to the turf the mob is actually standing on, begins at step_x+bound_x on the left and step_y+bound_y on the bottom.

The physical position of the bounding box is not affected by the pixel_x/y/z vars. Those are still strictly visual offsets.

The turfs the mob is covering can be read from the read-only locs var. The mob will also appear in the contents of those turfs.

Note: This means if an atom is in a turf's contents, its loc is not necessarily that turf. The contents list is made to include "overhangers" from another tile for ease of use.

Movement

All of the step and walk procs have been upgraded to take an additional argument, which is the speed at which the atom should move. If that argument is left out, the atom's own step_size is used by default. The step_size determines how fast the step_x and step_y values will change when moving.

Move() has two new arguments that handle the position change gracefully. These are the step_x and step_y values for the target location.

Pixel movement changes the behavior of the Move() proc, because a lot of things are possible that were not possible when BYOND only supported moving one tile at a time. For starters, a Move() is either a "slide" or a "jump" depending on the distance. A slide is when the move can be stopped partway; a jump is strictly pass/fail. Anything greater than one tile and the mover's regular step_size is considered a jump. Changing z levels is also a jump, as is moving to/from a non-turf.

If step_x and step_y aren't within a good range, the new loc and the step_x/y values may be changed so that the southwest corner of the mover's bounding box is standing on its actual loc, or as close to it as possible.

Enter() and Exit() can be called for several turfs and/or areas, not just one at a time. It is also possible for them not to be called at all, if the moving atom moves within a turf but doesn't cross a new turf boundary. Enter() and Exit() are only called when first attempting to enter or fully exit. The behavior of these procs depends on world.movement_mode; in legacy mode, they look at some of the contents of the turfs as well as the turfs themselves, to preserve behavior found in older BYOND versions.

Cross() and Uncross() are the equivalent of Enter() and Exit() but apply to objects the mover will either overlap or stop overlapping. (For turfs, Enter() and Exit() call these procs by default, since the mover is both stepping into and onto a turf.) Likewise Crossed() and Uncrossed() are the equivalents of Entered() and Exited().

If an atom is sliding, its movement can be halted if it encounters an obstacle partway along its route. Bump() will still be called for any obstacles the atom runs into, but Move() will return the number of pixels moved (the most in any direction). When sliding at a speed so fast that the distance is bigger than the atom itself, the move will be split up into several smaller slides to avoid skipping over any obstacles.

Gliding, which is used to show smooth movement between atoms in tile movement, is mostly not used in pixel movement. It only applies when the client uses a higher fps than the server.

Pixel procs

The bounds() and obounds() procs have been added to grab a list of atoms within a given bounding box. That box can be relative to an atom, or in absolute coordinates.

bounds_dist() tells the distance between two atoms, in pixels. If it is positive, that is the minimum distance the atoms would have to traverse to be touching. At 0, they are touching but not in collision. A negative value means the two atoms are in collision.


Projection matrix

See also:
Particle effects
transform var (atom)
matrix
Color matrix

Note: Currently this feature applies only to particle effects, using the transform var.

Normally icons in BYOND can only be transformed in 2D, using a simple 3x3 matrix. This is represented by the /matrix object, which cuts off the last column because it isn't used. However particles can have coordinates in x, y, and z, and the whole particle set can be given a transformation matrix that handles all three dimensions.

Simple 2D transforms

The easiest transformation for particles is a simple 2D one, which you can do by setting the particle datum's transform var to a /matrix object.

          a d 0
x y 1  *  b e 0  =  x' y' 1
          c f 1

When an x,y point is multiplied by the matrix, it becomes the new point x',y'. This is equivalent to:

x' = a*x + b*y + c
y' = d*x + e*y + f

This is called an affine transform because all the operations are "linear" in math terms. (That is, every term in the formula above has a single variable, not raised to a higher power than 1.)

3x4 matrix (x,y,z with translation)

3D affine transforms of this type are also affine transformations. There is no special object for this so a list is used (see below).

            xx xy xz 0
x y z 1  *  yx yy yz 0  =  x' y' z' 1
            zx zy zz 0
            cx cy cz 1

The way to read the vars above is that the first letter says what input component is being transformed (x,y,z, or c for "constant"), and the second letter is the output component.

x' = xx*x + yx*y + zx*z + cx
y' = xy*x + yy*y + zy*z + cy
z' = xz*x + yz*y + zz*z + cz

To use this kind of matrix, you can cut off the 4th column and provide the values in a list form, in row-major order:

list(xx,xy,xz, yx,yy,yz, zx,zy,zz, cx,cy,cz)

Note the 4th row is also optional.

4x4 matrix (x,y,z,w with projection)

This is the most interesting matrix, since if you use all 4 columns you're actually altering an "axis" called w. This isn't a real axis, but is just a number that the resulting vector will be divided by.

            xx xy xz xw
x y z 1  *  yx yy yz yw  =  x'w' y'w' z'w' w'
            zx zy zz zw
            wx wy wz ww

w' = xw*x + yw*y + zw*z + ww
x' = (xx*x + yx*y + zx*z + wx) / w'
y' = (xy*x + yy*y + zy*z + wy) / w'
z' = (xz*x + yz*y + zz*z + wz) / w'

In a regular affine transform, w always stays at 1. In projection you can think of w as a distance from the "camera". 1 is where objects are their "normal" size. If you make the z value affect w' by setting zw, you basically make an object look smaller at higher z values.

This is a simple projection matrix where x,y,z are left untouched, but there's a projection effect. The "D" value is how far away the "camera" is from z=0, so a point at z=D looks like it's twice as far away.

1  0  0  0
0  1  0  0
0  0  1  1/D
0  0  0  1

This 4x4 matrix is handled as a list just like the 3x4 affine matrix:

list(xx,xy,xz,xw, yx,yy,yz,yw, zx,zy,zz,zw, wx,wy,wz,ww)

Regular expressions

See also:
regex datum
regex proc
findtext proc
replacetext proc
splittext proc
REGEX_QUOTE proc

Regular expressions are patterns that can be searched for within a text string, instead of searching for an exact match to a known piece of text. They are much more versatile for find and replace operations, and therefore useful for parsing, filtering, etc.

Some example regular expressions are:

PatternCodeMeaning
B.*Dregex("B.*D")Find B, followed by any number of characters (including none), followed by a D.
[0-3]regex(@"[0-3]")Find any digit from 0 to 3
foo|barregex("foo|bar","i")Find foo or bar, case-insensitive
\d+regex(@"\d+","g")Find all sequences of digits

These are some of the patterns you can use. If you want to use any of the operators as an actual character, it must be escaped with a backslash.

It is highly recommended that you use raw strings like @"..." for your regular expression patterns, because with a regular DM string you have to escape all backslash \ and open bracket [ characters, which will make your regular expression much harder for you to read. It's easier to write @"[\d]\n" than "\[\\d]\\n".

PatternMatches
a|ba or b
.Any character (except a line break)
^Beginning of text; or line if m flag is used
$End of text; or line if m flag is used
\ABeginning of text
\ZEnd of text
[chars]Any character between the brackets. Ranges can be specified with a hyphen, like 0-9. Character classes like \d and \s can also be used (see below).
[^chars]Any character NOT matching the ones between the brackets.
\bWord break
\BWord non-break
(pattern)Capturing group: the pattern must match, and its contents will be captured in the group list.
(?:pattern)Non-capturing group: Match the pattern, but do not capture its contents.
\1 through \9Backreference; \N is whatever was captured in the Nth capturing group.
Modifiers
Modifiers are "greedy" by default, looking for the longest match possible. When following a word, they only apply to the last character.
a*Match a zero or more times
a+Match a one or more times
a?Match a zero or one time
a{n}Match a, exactly n times
a{n,}Match a, n or more times
a{n,m}Match a, n to m times
modifier?Make the previous modifier non-greedy (match as little as possible)
Escape codes and character classes
\xNNEscape code for a single character, where NN is its hexadecimal ASCII value
\uNNNNEscape code for a single 16-bit Unicode character, where NNNN is its hexadecimal value
\UNNNNNNEscape code for a single 21-bit Unicode character, where NNNNNN is its hexadecimal value
\dAny digit 0 through 9
\DAny character except a digit or line break
\lAny letter A through Z, case-insensitive
\LAny character except a letter or line break
\wAny identifier character: digits, letters, or underscore
\WAny character except an identifier character or line break
\sAny space character
\SAny character except a space or line break
Assertions
(?=pattern)Look-ahead: Require this pattern to come next, but don't include it in the match
(?!pattern)Look-ahead: Require this pattern NOT to come next
(?<=pattern)Look-behind: Require this pattern to come before, but don't include it in the match (must be a fixed byte length)
(?<!pattern)Look-behind: Require this pattern NOT to come before (must be a fixed byte length)

The optional flags can be any combination of these:

FlagMeaning
iCase-insensitive matching
gGlobal: In Find() subsequent calls will start where this left off, and in Replace() all matches are replaced.
mMulti-line: ^ and $ refer to the beginning and end of a line, respectively.

After calling Find() on a /regex datum, the datum's group var will contain a list—if applicable—of any sub-patterns found with the () parentheses operator. For instance, searching the string "123" for 1(\d)(\d) will match "123", and the group var will be list("2","3"). Groups can also be used in replacement expressions; see the Replace() proc for more details.


Understanding the renderer

To get the most out of BYOND's visual effects, it helps to understand how the map is displayed.

Every atom has an appearance that holds all of its visual info (and sometimes a little non-visual info). This appearance has to be turned into sprites in order to be rendered.

Although many atoms need little more than a simple icon and icon_state and produce only a single sprite, some are more complex with overlays, underlays, maptext, etc. Also there may be image objects and visual contents involved, although they're not part of the atom's appearance.

For a simple icon and icon_state, just one sprite is generated. The client looks up the icon it's given. Then it looks up an icon state, which may be influenced by whether the atom is moving or not since you can have moving and non-moving icon states. Then it determines which direction to draw and which frame of the icon's animation (if any) to use.

So with several simple icons, and not worrying about layers for now, a list of sprites lays out like this:

Atom #1
Atom #2
Atom #N

Overlays and underlays

Now let's consider what happens when an appearance has overlays.

Underlay #1
Underlay #N
Main icon
Overlay #1
Overlay #N

The underlays list is processed first, then overlays. These lists contain appearances themselves, rather than actual atoms. This means that overlays are recursive: an overlay can have overlays itself. To picture how that works, just replace one of the overlays above with another list.

Underlay #1
Underlay #2
Main icon
Underlays of overlay #1
Overlay #1 icon
Overlays of overlay #1
Overlay #2

Image objects and visual contents

Any atom can have an image object attached, which can be shown to only specific players. Most atoms, and image objects, can have visual contents that display other atoms as if they're overlays.

Underlays
Main icon
Overlays
Image objects
Visual contents

As you see this is very similar to overlays. Just like overlays, image objects and visual contents have appearances of their own (and may also have their own images or visual contents), so this may be recursive as they add new overlays, etc.

A couple of things to keep in mind:

Maptext and particles

Any appearance may have maptext attached. That maptext draws above the icon but is grouped with it. That grouping will be discussed further below.

Particle effects also get grouped with the main icon in a similar way to maptext.

For simplicity, from this point forward the diagram will just treat underlays, overlays, image objects, and visual contents as overlays.

Main icon
Maptext
Particles
Overlays

Color, transform, and filters

An appearance's color and alpha vars (from here forwarded they'll just be referred to by color) and transform are inherited by any overlays, which also includes images and visual contents. You can avoid that inheritance by giving those overlays special appearance_flags: RESET_COLOR, RESET_ALPHA, and RESET_TRANSFORM.

The appearance's filters are only applied to the main icon.

Main icon
Maptext
Main color, transform, and filters apply
Overlays
color and transform are inherited from Main
filters are not inherited from Main

When color and transform are inherited, they "stack". The inherited color and transform values are applied after those of the overlays.

KEEP_TOGETHER and KEEP_APART

There are times it's desirable for an appearance and all its overlays to be treated as a single unit so any colors or filters can be applied all at once. One simple example is if the appearance has an alpha of 128 to make it translucent, you probably want to draw the whole atom faded instead of drawing each sprite faded, one on top of the other.

By using the KEEP_TOGETHER value in appearance_flags (called KT for short), an appearance will group all of its underlays and overlays together. If this is an atom with image objects and visual contents, those will be grouped with it as well.

KT group
Main color, transform, and filters apply
Main icon
Maptext
Overlays

With KEEP_TOGETHER all of these sprites are rendered to a temporary drawing surface, and then the main appearance's color, transform, and filters are all applied to the combined drawing. This comes with a trade-off, since you can no longer use flags such as RESET_COLOR to opt out of inheritance.

If an overlay doesn't want to be part of a KT group, it can use the KEEP_APART flag (KA for short). If there are multiple nested KT groups, KA will only escape the innermost group.

If an overlay inside a KT group has a different plane than the group's owner, it will be separated as if it defined KEEP_APART, except it can escape multiple nested groups.

Layers and planes

Any appearance can have a layer or plane, and these influence how it gets sorted. (There's also a concept called a "sub-plane" that's influenced by whether an atom is a HUD/screen object or special layers like BACKGROUND_LAYER.)

If a sprite is created with FLOAT_LAYER (any negative value counts as a floating layer) its layer has to be resolved, or "unfloated". The main sprite for an atom can never float; it has to have a real layer. Its overlays and underlays with floating layers will reorder themselves in numerical order, then look for the next closest sprites in the rendering list that has a non-negative layer.

A similar process happens with FLOAT_PLANE. Planes can have negative values but FLOAT_PLANE and the values close to it are special. Sprites with floating planes have to resolve those as well.

Once all atoms that will appear on the map are assembled into a rendering list of sprites, the order in which they're rendered on the map is determined in this order:

  1. The plane var matters most.
  2. Subplane is counted next. E.g., HUD objects render above non-HUD objects.
  3. Depending on world.map_format, layer or physical position determine the drawing order from here.
  4. After everything else has been checked, the order the sprites were generated in is the final tie-breaker.

In a typical topdown map, layer is basically all that matters after the plane and subplane are taken into account. There is a legacy concept called micro-layers that helps break ties between sprites with the same layer; for instance if an atom is moving it's usually desirable to draw it above other atoms with the same layer; this applies only to topdown maps.

Plane masters

Sometimes it's helpful to group multiple sprites on one plane as if the plane itself were a KT group. For this, appearance_flags has a value called PLANE_MASTER. An object with this flag will act as a "parent" for everything else on the plane. All other sprites on the plane will be grouped together and rendered on a temporary drawing surface, and then the plane master's color, transform, and filters will be applied.

A plane master does not, however, get an icon or maptext of its own; they're simply ignored. It can have overlays added to the group.

Advanced topics

There are other topics not covered in this article, such as render targets and special map formats. Any details on how those features impact rendering are discussed in their own articles.


Side-view maps

See also:
map_format var (world)
icon_size var (world)
dir var (client)
pixel_w var (atom)
pixel_z var (atom)
screen_loc var (movable atoms)
Big icons
Isometric maps
Topdown maps
HUD
BACKGROUND_LAYER
EFFECTS_LAYER
TOPDOWN_LAYER

The side-view map format is used for 3/4 perspective, where the map is basically similar to a top-down view but is usually foreshortened. Just like with isometric projection, tiles that are closer to the bottom of the screen are considered to be closer to the viewer. This is a form of pseudo-3D in which the 2D icons used by BYOND can be arranged in a way to give the appearance of three dimensions.

It is important to remember that this is an illusion of 3D, not real 3D.

The layer var behaves much the same way it does in ISOMETRIC_MAP mode.See isometric maps for more information.

When using this mode you may want to use a foreshortened world.icon_size, like a 32x24 format instead of 32x32 for example, and use taller icons for any vertical structures like walls or buildings. If you set world.icon_size to use foreshortening, then pixel_y (or pixel_x, depending on the orientation of client.dir) will be adjusted for you; the same applies to step_x and step_y. For example, with world.icon_size set to "64x32", the physical tile—what you would see if you were to look at it straight down from above— is considered to be 64x64, so you would need pixel_y=64 or step_y=64 to offset by a whole tile. This adjustment does not apply to screen objects, pixel_w, or pixel_z.


Tiled icons

See also:
icon
procs (icon)
map_format var (world)
icon_size var (world)
Big icons

In BYOND 3.0, any file like a large .bmp would be treated like a regular icon that had been broken up into several tile-sized icon states. All tiles then were 32x32 pixels. An image that was 100x100 would therefore take at least 4x4 tiles to display. The icon was padded to the right and the top with blank space to become an even multiple of 32x32, and then broken up into sections. The lower left section was given an icon_state of "0,0", the next to the right was "1,0", and so on, up to the upper right which was "3,3". Another icon state, a 32x32 thumbnail of the big image, was also included.

BYOND 4.0 expanded on this concept by allowing icons to be defined that had individual graphics bigger than 32x32, and it would break each one up into tiles just like 3.0 did. If an icon had a state called "open" then it might break down into "open 0,0", "open 1,0", and so on, while the actual "open" state would be a thumbnail image. To show the whole image, you would have to have a separate atom or overlay for each individual tile.

In newer versions, breaking big icons into tiles is no longer done by default. Instead, icons are shown and manipulated in their native size. To use the old method of breaking icons into tiles, set world.map_format to TILED_ICON_MAP. This is the default for all projects compiled before version 455.

When using tiled icons, there are some important things to note:

This example shows a big icon being applied to an atom in tiled mode, as overlays:

Example:

// icon is 3 tiles wide by 2 high icon_state = "0,0" // A temporary object used for the overlays var/obj/O = new O.icon = icon O.layer = FLOAT_LAYER for(var/tile_y=0, tile_y<2, ++tile_y) for(var/tile_x=0, tile_x<3, ++tile_x) if(tile_x && tile_y) O.pixel_x = tile_x * 32 O.pixel_y = tile_y * 32 O.icon_state = "[tile_x],[tile_y]" overlays += O

Topdown maps

See also:
map_format var (world)
icon_size var (world)
dir var (client)
layer var (atom)
plane var (atom)
screen_loc var (movable atoms)
Big icons
HUD
Isometric maps
Side-view maps
Understanding the renderer

By default, BYOND displays all maps in top-down format, so world.map_format is set to TOPDOWN_MAP unless you say otherwise. This view means players are looking down on the map, and "north" corresponds to the top of their screen. (This can be changed by setting client.dir.)

A related map_format, used by older games, is TILED_ICON_MAP. This is also topdown but it handles icons differently.

In this form, the layer var behaves exactly as you would expect: Icons with a lower layer are drawn beneath icons with a higher layer. The only exception is when you use big icons, which will be drawn above any other icons on the same layer. Also an atom's underlays will be drawn behind it unless their layer is changed, and its overlays will draw in front of it unless otherwise stated.

Topdown mode also guarantees that world.view or client.view will set the exact screen size used by the HUD, except for HUD objects that appear outside of the normal bounds.

Screen objects (also called the HUD) cannot be intermixed with topdown icons. They will appear on top of other icons, unless using a lower plane or a special layer like BACKGROUND_LAYER.


TOPDOWN_LAYER

See also:
layer var (atom)
map_format var (world)
BACKGROUND_LAYER
EFFECTS_LAYER
stddef.dm file

TOPDOWN_LAYER is a special high value that can be added to the regular layer of any atom. This is only available when using a non-topdown world.map_format, such as isometric mapping.

The purpose of this value is to make an atom appear as if it belongs in a top-down map, when using a map_format other than TOPDOWN_MAP or TILED_ICON_MAP. This can be handy for title screens, or for special battle maps or the inside of a building in an RPG.

When using this special layer, it should be added to the layer an atom normally uses. For instance a turf should have a layer of TOPDOWN_LAYER + TURF_LAYER. Usually you will want one part of the map to have TOPDOWN_LAYER, and for players to be unable to walk to there from the regular map. Mixing topdown icons and icons in the normal map_format in view of each other could look very strange. For safety's sake, the easiest thing to do is to keep them on separate z layers.

This can be mixed with EFFECTS_LAYER. Anything in TOPDOWN_LAYER will display on top of EFFECTS_LAYER, and TOPDOWN_LAYER + EFFECTS_LAYER will be above both.

This can also be mixed with BACKGROUND_LAYER, which takes priority over everything else.

Images or overlays with FLOAT_LAYER can be left alone. They will automatically have the same layer as whatever atom they are attached to.


Unicode

See also:
text

BYOND was originally written to handle 8-bit ("ANSI") characters only. However as time has marched on, Unicode has become ubiquitous for supporting multiple languages, special characters, and emojis. To adapt to this, BYOND now supports Unicode.

When ANSI was king, every character was exactly one byte in width, because the only valid characters were between 1 and 255. (And technically, BYOND reserved 255 for its own use.) Now, BYOND uses an encoding called UTF-8 to store characters that can't fit in one byte.

UTF-8 breaks up characters with codes of 128 or higher into multiple bytes, like so:

Character codeSize in bytes
0 - 0x7F1
0x80 - 0x7FF2
0x800 - 0xFFFF3
0x10000 - 0x10FFFF4

Text handling

Importantly, BYOND's text procs are based on the byte position, not the character position which may be lower. In other words, length("abcdéfg") is greater than 7; it's 8, because é takes up 2 bytes in UTF-8. That also means f is at position 7, not position 6.

Why do the text procs work with byte position instead of character position? Because ultimately, it's faster. Going by character position would require counting every byte in a string (at least when it uses UTF-8) until the right character position was found. This would be detrimental to performance in most cases.

For the most part, this distinction should be fairly invisible to you. Most code isn't going to encounter problems, but if you do a lot of text processing you should be aware of it.

In particular, text2ascii() returns the Unicode value at a specific position, which may cover several bytes. If you loop through a string calling this proc for each character, you'll have to make adjustments for cases when multiple bytes have been read.

The read-only [] index operator also uses byte positions.

If you read a byte or cut text at an inappropriate point, any broken characters resulting from the cut will be turned into the Unicode replacement character � which is 0xFFFD.

_char procs

Most of the text handling procs have slower _char versions (e.g., copytext_char) that use character positions instead of byte positions.

These should be used sparingly if at all; whenever it's possible to use byte positions, you should. When you do use a _char version of a proc, prefer using -offset instead of length_char(text)-offset for positions near the end of the string. Most text procs allow negative position values that count backwards from the end, and counting a small number of characters backward is faster than counting a lot of characters going forward.

Old code

Code written in ANSI will be up-converted to UTF-8 by Dream Maker, based on your current locale when the code is loaded.


User interface skins

See also:
winset proc
winget proc
output proc
winclone proc
winexists proc
winshow proc
controls
parameters
macros (skin)
commands

BYOND games used to have very limited interface options, all effectively sharing the same layout. In BYOND 4.0, skins were introduced, allowing developers more control over the layout.

A skin consists of macro sets for keyboard/gamepad input, menus, and windows and/or panes. All of these are considered controls that a game can interact with via winset(), winget(), output(), and a few other procs.

About the simplest possible skin is a single window with a single map control, and a single macro set.


client commands

Several commands can be executed on the client that are not verbs, but raw instructions for Dream Seeker.

.winset "[control.param=value;...]"
Sets parameters in response to a menu or button command (or a manually typed command). You can set more than one by separating them with semicolons. This command has a more complex format for conditional instructions (see below).
.output control text
Sends output to a control. The text does not need quotes, but backslashes, newlines, and tabs should be escaped with a backslash. This works similarly to the output() proc. If text is omitted, the control is cleared..
.options
Shows the Options & Messages box.
.reboot
Reboots the world, when Dream Seeker is also acting as a server.
.reconnect
Reconnects to the same world.
.host
Opens hosting options box, when Dream Seeker is also acting as a server.
.profile
Opens the profiler. On a remote connection you may not have access to profile server procs, but you can look at the client and network profilers.
.screenshot
Saves a screenshot of the map. If there's more than one map control, the default map is used.
.screenshot auto
Saves a screenshot of the map, but does not prompt for a filename. The file will be saved in the client's user directory in BYOND/screenshots.
.gamepad-mapping
Opens the gamepad mapping dialog. Helpful if the user's gamepad is not supported or not configured to their liking.
.command
Prompts the user to enter a command, which can be one of these commands as well.
.configure option value
Toggle certain Dream Seeker config options, such as .configure graphics-hwmode on. The only supported options you can use are graphics-hwmode, sound, and delay which is an old mechanism for dynamically adapting to network delay. (Usually the delay is reset to 0.)
.quit
Closes Dream Seeker.

Conditional Winset

The .winset command allows you to use conditional expressions, like so:

condition ? choice1 : choice2

The condition is the same as any other parameter you might use in .winset, but instead of setting the parameter, it checks to see if it's true. If so, then the parameters in choice1 will be set. Otherwise, the parameters in choice2 are set. This example makes the window background red if bigbutton is checked.

.winset "bigbutton.is-checked=true ? window.background-color=#ff0000 : window.background-color=none"

If you want to look for values that don't match instead of values that do, use != instead of = in the condition.

.winset "bigbutton.is-checked!=false ? window.background-color=#f00 : window.background-color=none"

The choice2 item is optional.

.winset "bigbutton.is-checked=true ? window.background-color=#f00"

Because it's often useful to do more than one thing at a time, choice1 and choice2 don't have to be just one parameter. You can use multiple parameters, but they are separated with a space instead of a semicolon. (A semicolon indicates the conditional expression is over.)

.winset "bigbutton.is-checked=true ? window.text-color=#fff window.background-color=#f00 : window.text-color=none window.background-color=none"

Embedded Winget

Commands that are initiated by the skin (like button.command, map.on-show, etc.) have a special syntax that allows you to include information that would normally require a winget call. By including [[something]] in the command, the double-bracketed text will be replaced by the result of running a winget on that parameter.

A value of [[id.parameter]] will run a winget on the control with the given ID. Just using [[parameter]] will run a winget for the control that initiated this command. You can also use parent in place of the ID to do something with the parent of the control, or parent.id for access to a sibling control. Position and size parameters can be further broken down by appending .x or .y to get at the numbers directly.

Several commands already support some special cases like [[*]] or [[width]] or such, where the special-case values are relevant to the command. An example is that in on-size the value of [[*]] is a size value. The Any macro, gamepad macros, and mouse macros, also support this syntax; see macros for more info.

You can choose how embedded wingets get formatted by following the value with as and a type, such as [[window.size as string]]. There are several types you can use, and different types of parameters get formatted differently:

arg
Value is formatted as if it's an argument on a command line. Numbers are left alone; booleans are 0 or 1; size and position have their X and Y values separated by a space; pretty much everything else is DM-escaped and enclosed in quotes.
escaped
DM-escape the value as if it's in a quoted string but do not include the quotes. Size and position values both use , to separate their X and Y values.
string
Value is formatted as a DM-escaped string with surrounding quotes.
params
Format value for a URL-encoded parameter list (see list2params), escaping characters as needed.
json
JSON formatting. Numbers are left unchanged; size or position values are turned into objects with x and y items; boolean values are true or false.
json-dm
JSON formatting, but DM-escaped so it can be included in a quoted string. Quotes are not included.
raw
Does not change the value's text representation in any way; assumes it's already formatted correctly for the purpose. This is similar to as arg but does no escaping and no quotes.

The arg type is the default, unless the [[...]] expression has double quotes on both sides, in which case escaped is the default.


controls (skin)

Control types:
Bar: A progress bar or slider
Browser: A browser
Button: A pushbutton or toggle button
Child: A container holding one or two panes, with a movable splitter
Grid: For table-like or list-like output
Info: Classic BYOND statpanel
Input: Command input or other user-entered text
Label: Non-interactive text label
Main: A window or pane that holds other controls
Macro: A keyboard/gamepad/mouse macro
Map: The game map display
Menu: An item in a drop-down menu
Output: Text output
Tab: A tab control holding multiple panes, showing one at a time
Parameters common to all controls:
id
is-disabled
parent
saved-params
type
Positionable controls only (not Macro or Menu):
anchor1, anchor2
background-color
border
drop-zone
flash
focus
font-family
font-size
font-style
is-visible
is-transparent
on-size
pos
right-click
size
text-color

Creating/Destroying at runtime

Controls can be created or deleted at runtime. (Only controls you created during runtime may be deleted.) To create a control, call winset() using the id of the new control, and the parameter list should include type, parent, and probably also pos, size, and any anchors.

To delete the control again, set its parent to a blank value.

Menu items and macros work similarly, except they have no positional info. For those, the name parameter is important when you create them, and you will either need command or (for macros) map-to to do anything with them.


bar control (skin)

A progress bar or interactive slider. This can be made to use several different orientations. Its value can be read or set as a percentage from 0 to 100.

Bar-specific parameters:
angle1, angle2
bar-color
dir
is-slider
on-change
value
width

browser control (skin)

A browser panel integrated into the skin.

Browser-specific parameters:
auto-format
on-hide
on-show
show-history
show-url
use-title

Browsers are capable of displaying HTML documents, and can also interact with the skin.

Browsers and popups

A longstanding behavior of BYOND is the ability to create a new browser window by sending an extra argument to the browse() proc. Since the advent of skins in BYOND 4.0, this behavior was kept. When you create a new browser popup, the window name you specify for the popup is used for the name of a new window control, and within that window there will be a new browser control simply called browser.

If you want to interact with the new browser, its full "decorated" id is windowname.browser.

Running JavaScript from DM

Sending output() to a browser will send a document to display there, but if you follow the browser's control name with a colon and a function name, you can call a JavaScript function in the document displayed within that browser.

Example:

var/list/info = list("name"="fridge", "power"=12) // send {"name":"fridge","power":12} to a JavaScript function usr << output(url_encode(json_encode(info)), "mybrowser:myJSfunction")

The text that you send as output will be parsed like URL parameters, where mutliple arguments to the function are separated by & or ;, which is why url_encode() is wrapped around the json_encode() call in this example.

Winset and Winget via JavaScript

To allow better access to the skin via JavaScript, two new URL formats have been added. If window.location is set to these from JavaScript in a browser control, they can be used to interact directly.

Winset URL: byond://winset?id=[control ID]&[property]=[value]&...

This works like an ordinary winset() call from the server. If id is omitted, it's the same as a winset with a null ID. You can also leave the id blank if you use "fully decorated" property names such as mybutton.is-checked instead of just is-checked.

Any text you use other than letters, numbers, hyphens, commas, and periods should be encoded via the encodeURIComponent() function in JavaScript.

Winget URL: byond://winget?callback=[callback function]&id=[control ID/list]&property=[property/list]

In this winget, the IDs and properties you want can be separated by commas if you want to retrieve more than one. The winget operation works via a callback function you must define in JavaScript. The callback is given just one argument, a JavaScript object with all of the properties you requested. For example, this URL:

byond://winget?callback=wgcb&id=button1&property=is-checked,size,background-color

...might send this to the callback function wgcb:

{
    "is-checked": true,
    "size": {
        "x": 60,
        "y": 20
    },
    "background-color": {
        "value": "none",
        "isDefault": true,
        "red": 236,
        "green": 233,
        "blue": 216,
        "alpha": 255,
        "css": "#ece9d8"
    }
}

The property names will be in the same format you would expect from winget(), so when you're looking at multiple elements' properties, you'll get the full names in id.property format. The values are always sent back in a convenient form for JavaScript to work with; in the case of size, position, and color these will always be objects.

An optional control parameter for the winget call can be used if you want to send data to a callback in a different browser control.


button control (skin)

A button that can be pressed to run a command, or possibly toggled.

Button-specific parameters:
button-type
command
group
image
is-checked
is-flat
text

child control (skin)

A container that can hold one or two panes. If it holds two panes, a splitter may appear between them. This control can therefore be used to subdivide a window or pane into smaller units.

Child-specific parameters:
is-vert
left, top
lock
right, bottom
show-splitter
splitter

grid control (skin)

A grid that contains multiple cells that can show various kinds of output data.

Grid-specific parameters:
cell-span
cells
current-cell
enable-http-images
highlight-color
is-list
line-color
link-color
show-lines
show-names
small-icons
style
visited-color

Sending output to a grid looks like this:

Example:

// output to column 3, row 2 winset(usr, "thegrid", "current-cell=3,2") usr << output("Text", "thegrid") // or even easier: usr << output("Text", "thegrid:3,2") // when is-list is true: usr << output("5th item", "thegrid:5")

You can output an atom to the grid, which can be clicked, dragged, etc. However, you should make sure that atom is not temporary and will persist until you no longer need it, or else the server may recycle it and the object in the cell will either disappear or be impossible to interact with anymore.

There are some limitations to output in grid controls:


info control (skin)

The classic BYOND statpanel, which contains both stat and verb tabs. This is technically a 3-column grid with a variable number of rows.

Info-specific parameters:
allow-html
highlight-color
multi-line
on-hide
on-show
on-tab
prefix-color
suffix-color
tab-background-color
tab-font-family, tab-font-size, tab-font-style
tab-text-color

Output to a statpanel is done via the stat() and statpanel() procs, during mob/Stat().

The same limitations that apply to grid output apply here.


input control (skin)

A text box into which the user can type. By default this is used for sending commands, but it can be used for other purposes as well.

Input-specific parameters:
command
is-password
multi-line
no-command
on-blur
on-focus
text

Note that when in "standard" mode of accepting user commands, built-in verbs like .click, or local commands like .winset, are not accepted when typed in. This kind of command can still be entered manually through the Client menu of the Options & Messages window.


label control (skin)

A text label that appears on the skin.

Label-specific parameters:
align
allow-html
image
image-mode
keep-aspect
text
text-wrap

macro control (skin)

A keyboard/gamepad/mouse macro, usually designed to run a command. The control is a means of interacting with the macro as an object, allowing some of its properties to be changed at runtime.

Macro-specific parameters:
command
map-to
name

main control (skin)

A container for other controls. The Main control takes two forms: a window or a pane.

A window exists independently and can be moved around on the screen. A pane has to be used within another container control such as a Child or Tab control.

Main-specific parameters:
icon
image
image-mode
inner-pos
inner-size
is-pane
keep-aspect
outer-pos
outer-size
title
on-status
Windows only:
alpha
can-close
can-minimize
can-resize
is-fullscreen
is-maximized
is-minimized
macro
menu
on-close
screen-pos
screen-size
statusbar
titlebar
transparent-color
Panes only:
can-scroll

The font parameters have no impact on a window's statusbar or titlebar; those are drawn by the operating system.


map control (skin)

A map that will display icons from the game.

Map-specific parameters:
icon-size
letterbox
on-hide
on-show
style
text-mode
view-size
zoom
zoom-mode

menu control (skin)

A menu item, that when activate will run a command.

Menu-specific parameters:
can-check
command
group
index
is-checked
name

output control (skin)

Displays text output.

Output-specific parameters:
enable-http-images
image
legacy-size
link-color
max-lines
style
visited-color

tab control (skin)

A tab control, where each tab holds a different pane.

Tab-specific parameters:
current-tab
multi-line
on-tab
tabs

macros (skin)

Macros are used to convert keyboard and gamepad events into actions. There are two ways this works: A macro can run a command, or in some cases (such as gamepad controls) it can be used to remap one control to another.

A collection of macros is called a macro set, and the window currently in use defines which macro set will be used via its macro parameter.

Macros can be changed at runtime. If a macro does not have an id, you can refer to it by its key combination (name). If you have a macro set named macro1 and have a Ctrl+E macro for instance, you could use winset() with "macro1.Ctrl+E". See the Macro control for information on which parameters you can change with winset().

The name of the macro is actually the full key combination as it would appear in the macro editor, like CTRL+E, Space+REP, or Alt+Shift+F1. This is not case-specific and it doesn't matter where you put modifiers like CTRL+, SHIFT+, etc.

The Any macro

Oftentimes it's desirable to keep track of key presses yourself rather than have a hundred different macros defined. BYOND makes this possible via the Any and Any+UP macros, which respond to any key or gamepad button. UP is the only allowed modifier for this macro, since other modifier keys are handled by this same macro.

Typically, you will want to use set instant=1 on the verbs that will be tied to the Any macro, so that keyboard input doesn't queue up and lag behind.

In the command that goes with this macro, [[*]] will be replaced with the name of the key or gamepad button that was pressed/released. (See "Embedded Winget" in client commands for more details on the [[...]] format.)

Mapping

The map-to parameter is used by mappings, which are like macros but are used to convert gamepad inputs easily and quickly to keyboard inputs. E.g., GamepadLeft can map to West which is the left arrow key. A set of default mappings will be added automatically at runtime if you don't include any gamepad mapping in your project.

Gamepads

BYOND will support up to four gamepads, and breaks up their input into the following categories:

See the list of available macros below for information on how to harness these inputs.

To let a user configure their gamepad, you need to call the client-side .gamepad-mapping command. Or, if they have access to the Options & Messages window and Dream Seeker's default menus, they can reach it from there. However it's a good idea to make this easy for them to find. Several common gamepads are already known by BYOND.

There is also the GamepadRaw macro, which is similar to Any in some ways and will avoid doing any processing (e.g. checking for dead zones on the analog sticks) so you can handle all input yourself. GamepadRaw does not rely on BYOND's controller configuration, so it will not, for instance, know that button 0 should be GamepadFace1. See below for more information on how to use this macro.

Mouse macros

You can add macros (not local player-defined ones) for any of the mouse input commands, thereby bypassing the normal mouse verbs. This can be helpful for designing custom setups where you don't want to have to parse the normal parameter string that provides most of the info, and instead want to provide data directly to the verb. You will want set instant=1 on any such verb.

Mouse macro commands use the [[...]] syntax to embed values, just like embedded wingets. These are the values you can include in a mouse macro:

Embedded keywordMeaning
actionName of the mouse action (e.g. MouseDown, MouseMove, etc.).
srcObject the mouse is touching, or dragging/dropping.
locTurf or statpanel that src is over; in a drag-drop you should split this into src.loc and over.loc.
buttonMouse button used for this action, if any: left, middle, or right.
dragMouse button currently used for dragging.
buttonsMouse buttons currently down or involved in this action, separated by commas.
keysModifier keys currently held (shift, ctrl, alt), separated by commas.
overObject the mouse is over in a drag/drop operation.
idControl ID; in a drag-drop you should split this into src.id and over.id.
iconThe icon offset (starting from 1,1 at the lower left) where the mouse action occurred.*
tileThe tile where the mouse action occurred, if relevant.*
visPixel coordinates relative to the icon's position on screen (same as icon but without taking transform into account).*
screen_locThe regular screen_loc cordinate string.*
screenscreen_loc coordinates but entirely in pixels starting at 0,0 from lower left.*
screen_tilescreen_loc coordinates but only the tile number starting at 1,1.*
screen_offsetscreen_loc coordinates but only the pixel offset from the tile, starting at 0,0.*
deltaWheel changes in a mouse wheel command.*
left, right, middle1 if this button is down or involved in this action, 0 otherwise
shift, ctrl, alt1 if this modifier key is held, 0 otherwise
link1 if the mouse is over a maptext link, 0 otherwise
cellGrid cell involved in a mouse action. In a drag/drop action, src.cell is the dragging cell and over.cell is the drop cell.
drag-cellAlias for src.cell.
drop-cellAlias for over.cell.
* Coordinate values are comma-separated, but you can follow them with .x or .y to get the individual X and Y numbers.

An example mouse macro command might look like this:

my-mousedown-verb [[src]] [[button]] "keys=[[keys as params]];drag=[[drag as params]]"

And the verb to go with it looks like this:

client // "in src" is the same as "in usr.client" here verb/my_mousedown_verb(object as anything in src, button as text, params as text)

In the example, the src value is a reference such as you would get with the ref() proc. It can be used as a verb argument directly and won't be enclosed by quotes by default. The button value is a string and the default formatting will put quotes around it. The keys and drag values were given the as params format specifier so they would behave as part of a parameter list.

In drag/drop actions, you can precede any value with src or over if there may be different information for the dragged object and the mouseover object/location. This also applies to things like keys, which by default will be the currently held keys but you can use src.keys to refer to the values from when the drag began.

Available macros

This is a list of all keys and gamepad events that can be used in macros.

Macro modifiers are part of the macro name, and control the conditions in which the macro will fire.
ModifierMeaning
SHIFT+This macro only counts if either Shift key is pressed.
CTRL+This macro only counts if either Ctrl key is pressed.
ALT+This macro only counts if either Alt key is pressed.
+REPIf a key/button is held down, this macro repeats.
+UPThis macro fires when the key/button is released.
Keyboard keys are the garden-variety macros. (This list is abridged to exclude keys probably no one has.)
KeyDescription
A - ZLetter key
0 - 9Number key
Numpad0 - Numpad9Numpad numbers
NorthUp arrow
SouthDown arrow
EastRight arrow
WestLeft arrow
NorthwestHome key
SouthwestEnd key
NortheastPage Up key
SoutheastPage Down key
CenterCenter key (numpad)
ReturnEnter / Return key
EscapeEsc key
TabTab key
SpaceSpace bar
BackBackspace key
InsertIns key
DeleteDel key
PausePause key
SnapshotSnapshot / Print Screen key
LWinLeft Windows key
RWinRight Windows key
AppsApps key
MultiplyMultiply key
AddAdd key
SubtractSubtract key
DivideDivide / Slash key
SeparatorSeparator / Backslash key
ShiftShift key (when not used as a modifier)
CtrlCtrl key (when not used as a modifier)
AltAlt key (when not used as a modifier)
VolumeMuteMute key
VolumeUpVolume up key
VolumeDownVolume down key
MediaPlayPausePlay/pause media key
MediaStopStop media key
MediaNextNext track key
MediaPrevPrevious track key
Special macros
AnyA special macro that can run a command on press/release of any key or gamepad button. UP is the only modifier allowed. In the command, [[*]] is replaced with the key/button name.*
GamepadRaw*Captures raw input from a gamepad, without regard to the adjustments done by the Gamepad Setup dialog. In the command, [[id]] is replaced by the name of the button or axis changed ("Button0" through "Button15" and "Axis0" through "Axis11"), [[value]] is replaced with the value of the button or axis, and [[*]] is equivalent to [[id]] [[value]].

* If no gamepad mappings are included in a game's interface, the default mappings are used instead, which will map the Dpad buttons to the arrow keys. This will cause the Any macro to register both a gamepad directional button and the mapped key on the same press. If you plan on using macros to capture gamepad input, you may wish instead to map any one of the directional buttons to "None", which will override the default gamepad mappings completely.

Gamepad buttons can use another gamepad button as a modifier (but not CTRL, SHIFT, ALT), and can be mapped to one or two keyboard keys or mouse buttons.
ButtonDescription
GamepadFace1A (Xbox), X (PS), bottom of diamond
GamepadFace2B (Xbox), Circle (PS), right of diamond
GamepadFace3X (Xbox), Square (PS), left of diamond
GamepadFace4Y (Xbox), Triangle (PS), top of diamond
GamepadL1Left top shoulder
GamepadR1Right top shoulder
GamepadL2Left bottom shoulder
GamepadR2Right bottom shoulder
GamepadSelectSelect / Back
GamepadStartStart / Forward
GamepadL3Left analog click
GamepadR3Right analog click
Directional buttons: only one can pressed at a time, and the diagonal buttons are virtual.
GamepadUpUp button
GamepadDownDown button
GamepadLeftLeft button
GamepadRightRight button
GamepadUpLeftUp+left virtual button
GamepadUpRightUp+right virtual button
GamepadDownLeftDown+left virtual button
GamepadDownRightDown+right virtual button
Gamepad analog sticks can have commands and/or map to GamepadDir, GamepadDir4, or Mouse. They can use a gamepad button as a modifier. In a command, [[x]] and [[y]] are replaced by coordinates, and [[*]] is replaced by both with a comma for separation.
GamepadLeftAnalogLeft analog stick
GamepadRightAnalogLeft analog stick
Gamepad Dpads†‡ can have commands or are used as mapping targets for analog sticks. A gamepad button can be used as a modifier. In a command, [[*]] is replaced by a direction number, which can be 0.
GamepadDirDpad, converted to one of the eight standard directions.
GamepadDir4Dpad, converted to a cardinal direction.

All of the gamepad macros defined above apply to the first gamepad. BYOND can now support up to four gamepads, and you can replace Gamepad in the names above with Gamepad2, Gamepad3, or Gamepad4 to access them. Each gamepad also has its own raw macro (i.e., Gamepad2Raw).

If you use a Dpad macro like GamepadDir as a map-to target, you don't have to specify gamepad 2-4 in map-to; the mapping will automatically know that when Gamepad2LeftAnalog is mapped to GamepadDir, it means Gamepad2Dir.

Mouse macros can have commands but not be used as mapping targets.
MouseDownMouse button pressed (replaces MouseDown verb)
MouseUpMouse button released (replaces MouseUp verb)
MouseClickA click action has occurred (replaces Click verb)
MouseDblClickA double-click action has occurred (replaces DblClick verb)
MouseOverMouse has moved over a new icon or entered/exited a control (replaces MouseEntered and MouseExited verbs)
MouseMoveMouse has moved to a new pixel of the same icon (replaces MouseMove verb)
MouseDragMouse has begin dragging or is over a new drop target (replaces MouseDrag verb)
MouseDragMoveMouse is dragging and is over a new pixel of the same drop target (replaces MouseDrag verb in situations where MouseMove would apply)
MouseDropMouse drag has been released over a target (replaces MouseDrop verb)
MouseWheelA wheel movement has occurred (replaces MouseWheel verb)
Mouse targets can only be used as mapping targets for another macro.
MouseThe mouse cursor, mappable by a gamepad analog stick.
MouseLeftButtonLeft button, mappable by a gamepad button.
MouseRightButtonRight button, mappable by a gamepad button.
MouseMiddleButtonMiddle button, mappable by a gamepad button.

parameters (skin)

Controls can be interacted with via winset() and winget() to change or read various parameters.

Parameters come in a few different formats:

The list of all controls which shows which parameters are universal, and each individual control type lists additional parameters that apply to that type specifically.

Note: In any parameter's "Applies to" section, "all" refers to positionable controls only, not Macro or Menu controls. Macro and Menu will be listed separately if supported.


align parameter (skin)

See also:
allow-html parameter
Applies to:
Label
Possible values:
center
left
right
top
bottom
top-left
top-right
bottom-left
bottom-right
Default value:
center

Default alignment of text/image, both horizontal and vertical.

A BYOND direction flag like WEST may be assigned to this parameter, or 0 for center alignment.


allow-html parameter (skin)

Applies to:
Label
Info
Format:
true/false
Default value:
false

Info control: Allow HTML tags to be used in stat() info. The same limitations apply as to the Grid control.

Label control: Currently, the label control will not actually use the HTML; it will simply strip it out. Full support may appear in a later version.


alpha parameter (skin)

See also:
transparent-color parameter
Applies to:
Main (window only)
Format:
number
Default value:
255

Opacity of the window, from 0 (invisible) to 255 (opaque).


anchor1, anchor2 parameters (skin)

See also:
pos parameter
size parameter
Applies to:
All (except Main)
Format:
none
x,y
Default value:
none

Anchors the control within the window or pane. If the anchor is not none, it is expressed as pecentages of the container's width and height. For example, an anchor of 100,100 means that the X and Y position are tied to the lower right of the container, and 50,0 is tied to the top center.

Setting only anchor1 will control the position of the control but won't affect its size.

Setting anchor2 as well will allow you to stretch the control as the container's size changes. You can think of this anchor1 controlling the top left corner, and anchor2 the bottom right corner.


angle1, angle2 parameters (skin)

See also:
dir parameter
width parameter
Applies to:
Bar
Format:
number
Default value:
angle1: 0
angle2: 180

The angle of the bar control's arc when its dir is clockwise or counterclockwise. Angles are measured clockwise from due north, so 0 is north, 90 is east, and so on. angle1 is the beginning of the arc, and angle2 is the end.


auto-format parameter (skin)

Applies to:
Browser
Format:
true/false
Default value:
false (was once true in old versions)

When true, the browser control will inject conditional scripting into HTML documents to make them behave nicer in very old browsers. However, it is unlikely there are any systems left that need this.


background-color parameter (skin)

See also:
text-color parameter
tab-background-color parameter
Applies to:
All
Format:
#rrggbb
none

The control's background color. The exact way this applies depends on the control.


bar-color parameter (skin)

See also:
background-color parameter
is-transparent parameter
Applies to:
Bar
Format:
#rrggbb
none

The color of the bar or slider.


border parameter (skin)

Applies to:
All
Possible values:
none
line
sunken
Default value:
none

Border type around the control or window. May not work the same in all controls.


button-type parameter (skin)

See also:
group parameter
is-checked parameter
Applies to:
Button
Possible values:
pushbutton: press once
pushbox: press to toggle
checkbox: press to toggle, and displays a checkmark if checked
radio: press to check, and other buttons with the same group will be unchecked
Default value:
pushbutton

Changes the type of button.


can-check parameter (skin)

See also:
group parameter
is-checked parameter
Applies to:
Menu
Format:
true/false
Default value:
false

If true, this menu item is toggled like a checkbox or radio button when clicked.


can-close parameter (skin)

See also:
on-close parameter
can-resize parameter
titlebar parameter
Applies to:
Main (window only)
Format:
true/false
Default value:
true

Allow the window to be closed, and also shows a system menu for the window.


can-minimize parameter (skin)

See also:
can-resize parameter
titlebar parameter
Applies to:
Main (window only)
Format:
true/false
Default value:
true

Allow the window to be minimized.


can-resize parameter (skin)

See also:
on-size parameter
can-minimize parameter
titlebar parameter
is-fullscreen parameter
Applies to:
Main (window only)
Format:
true/false
Default value:
true

Allow the window to be resized or maximized.

If is-fullscreen is true, can-resize is ignored, so this value represents the state of the window when is-fullscreen is turned off again.


can-scroll parameter (skin)

See also:
on-size parameter
size parameter
Applies to:
Main (pane only)
Possible values:
none
horizontal
vertical
both
Default value:
none

Allow this pane to retain its horizontal and/or vertical size and show scrollbars if necessary, instead of shrinking to fit the container.


command parameter (skin)

See also:
Commands
Applies to:
Button
Input
Macro
Menu
Format:
string

Command executed when this control is activated.

For the Input control, whatever the user types in follows this command. If your command starts with an exclamation point !, everything after the ! is shown as a default prompt that may be cleared by the user.


cell-span parameter (skin)

See also:
cells parameter
Applies to:
Grid
Format:
columns,rows
Default value:
1x1

The span of the current grid cell; it can be merged with cells to the right and down. If is-list is true, this setting is ignored. This setting is only available at runtime.


cells parameter (skin)

See also:
cell-span parameter
current-cell parameter
is-list parameter
Applies to:
Grid
Format:
columns,rows
items
Default value:
0x0

The number of columns and rows in the grid. Using -1 for either columns or rows will leave that value unchanged.

If is-list is true, this value can be set to a single number.


current-cell parameter (skin)

See also:
cell-span parameter
cells parameter
is-list parameter
Applies to:
Grid
Format:
columns,rows
items
Default value:
0x0

The active cell. Any output sent to the grid, that is not sent to a specific cell, will go into this cell.

If is-list is true, this value can be set to a single number.


current-tab parameter (skin)

See also:
on-tab parameter
tabs parameter
Applies to:
Tab
Format:
string

The name of the pane in the active/default tab. If set to a pane that is not currently in this tab control, the pane by that name will be added as another tab.


dir parameter (skin)

See also:
value parameter
angle1, angle2 parameters
width parameter
Applies to:
Bar
Possible values:
north
south
east
west
clockwise
counterclockwise
Default value:
east

The direction/orientation of the bar. As the value increases the bar will move further in this direction.

Shorthand values like cw and ccw can be used, or also numerical BYOND directions.


drop-zone parameter (skin)

See also:
mouse handling
Applies to:
All
Format:
true/false
Default value:
true for Grid, Info, Map
false for everything else

True if dragged objects may be dropped here. Default is true for Map, Info, and Grid controls, false for others. When in use, this will be the value of the over_control argument in MouseDrop() if you drop an atom here.

Grids can also add drag-cell and drop-cell to mouse proc parameters. The mouse procs' src_location and over_location arguments are in the form "[column],[row]" (or "[item"] if is-list is true) when dragging to/from a grid cell.

In Info controls, src_location and over_location in mouse procs will be the name of the statpanel tab.


enable-http-images parameter (skin)

See also:
small-icons parameter
style parameter
Applies to:
Grid
Output
Format:
true/false
Default value:
false

Allows images to be pulled from the Web when using the <img> tag; otherwise only locally stored images can be shown.


flash parameter (skin)

Applies to:
Main (window only)
Format:
number
Default value:
0

Set to a positive number to make the window flash that many times, -1 to flash forever, and 0 to stop flashing.


focus parameter (skin)

See also:
id parameter
winget proc
Applies to:
All
Format:
true/false
Default value:
false

This parameter is true if this control currently has focus.

This is also a special read-only global parameter. Calling winget() with no id and focus as the parameter will return the id of the currently focused control, if any.


font-family parameter (skin)

See also:
font-size parameter
font-style parameter
tab-font-family, tab-font-size, tab-font-style parameters
Applies to:
All
Format:
string

Leave blank to use the default font. This can be used for CSS-style fallback fonts, e.g. "Arial,Helvetica".

You can include fonts in your resource file, making them available to the client, like so:

var/list/extra_resources = list(\ 'myfont.ttf', 'myfont_bold.ttf')

font-size parameter (skin)

See also:
font-family parameter
font-style parameter
tab-font-family, tab-font-size, tab-font-style parameters
Applies to:
All
Format:
number
Default value:
0

Point size of the font, or leave at 0 for the default size.

The Output control behaves differently for legacy reasons, unless legacy-size is false.


font-style parameter (skin)

See also:
font-family parameter
font-size parameter
tab-font-family, tab-font-size, tab-font-style parameters
Applies to:
All
Possible values:
bold
italic
underline
strike
Default value:
empty

Sets the font style. Any combination of the above values may be used, or none of them. Multiple values may be separated by spaces or commas.


group parameter (skin)

See also:
button-type parameter
can-check parameter
is-checked parameter
Applies to:
Button
Menu
Format:
string

Used for "radio" buttons and menu items, where only one of them in the same group may be checked at a time. This value is a text string, or may be left empty.

Buttons in different windows/panes, or menu items in another menu/submenu, are always treated as a different group.


highlight-color parameter (skin)

See also:
text-color parameter
background-color parameter
Applies to:
Grid
Info
Format:
#rrggbb
none
Default value:
#00ff00

The color used to highlight moused-over statpanel items or verbs. In grids, this color is used when hovering over objects or links.


icon parameter (skin)

See also:
title parameter
titlebar parameter
Applies to:
Main
Format:
'file'
Default value:
empty

Custom icon used for the window. If no icon is specified, the Dream Seeker icon is used by windows by default.

If this control is a pane, its icon will appear on the tab if the pane is inside a tab control. Lack of an icon will mean no icon appears in the tab.

Note: The Windows .ico format is not used. Only image formats BYOND can already use are supported.


icon-size parameter (skin)

See also:
zoom parameter
zoom-mode parameter
Applies to:
Map
Format:
number
Default value:
0

Size, in pixels, of icons on the map. A size of 0 stretches to fit available space.

This parameter has been deprecated. Use zoom instead.


id parameter (skin)

See also:
parent parameter
type parameter
Applies to:
All
Format:
string

The name of this control. Read-only.

If this is a Main control, the name should always be unique. For others, it is usually still a good idea to use a unique name, but they can be referenced by window.id at runtime.

You can use a colon in front of the type to refer to the default control of a certain type, if one exists, e.g. :map is the default map.


image parameter (skin)

See also:
image-mode parameter
keep-aspect parameter
Applies to:
Button
Label
Main
Output
Format:
'file'

A background image to show in this control.

In the Output control this image is always tiled.

Note: Icons displayed in the output control will not show the background image underneath their transparent parts, but will instead show the background color.

For Label and Main, use image-mode to control how the image is displayed.


image-mode parameter (skin)

See also:
image parameter
keep-aspect parameter
Applies to:
Label
Main
Possible values:
center
stretch
tile
Default value:
center

Determines how the background image is displayed.


index parameter (skin)

Applies to:
Menu
Format:
number
Default value:
1000

Moves the menu item to the Nth position among its siblings. 0 or less is no change. Write-only.


inner-pos parameter (skin)

See also:
pos parameter
outer-pos parameter
inner-size parameter
outer-size parameter
Applies to:
Main
Format:
x,y

Read-only.

Reads the position where the window's interior contents begin (i.e., not counting titlebar, statusbar, borders, etc.), relative to its outer-pos.


inner-size parameter (skin)

See also:
size parameter
outer-size parameter
inner-pos parameter
Applies to:
Main
Format:
widthxheight

Read-only.

If the control is a window, this refers to its current interior size: i.e., not counting titlebar, statusbar, borders, etc. If it's maximized, this will be the true size of the window interior, as opposed to size which is the interior size once this window is no longer maximized.

If this control is a pane and can-scroll is true, this is the size of the display area not including the scrollbars.


is-checked parameter (skin)

See also:
button-type parameter
can-check parameter
group parameter
Applies to:
Button
Menu
Format:
true/false
Default value:
false

True if the button or menu item is checked. Menu items can set this even if can-check is false.


is-default parameter (skin)

See also:
id parameter
parent parameter
type parameter
Applies to:
All
Format:
true/false
Default value:
false

Specifies that this is a default control. This should be true for your main window, and for your primary map, info, output, input, and browser controls.

The default control of a given type can be referenced in winset() and other skin-related procs by the name ":type", e.g. ":map".

Changing this value at runtime should be avoided, especially for windows. Results may be unpredictable.


is-disabled parameter (skin)

See also:
is-checked parameter
is-visible parameter
Applies to:
All
Macro
Menu
Format:
true/false
Default value:
false

Disables the control, menu item, or macro.


is-flat parameter (skin)

See also:
button-type parameter
Applies to:
Button
Format:
true/false
Default value:
false

Gives this button a flat appearance instead of pseudo-3D highlights.


is-fullscreen parameter (skin)

See also:
can-resize parameter
titlebar parameter
is-maximized parameter
is-minimized parameter
size parameter
outer-size parameter
screen-pos parameter
screen-size parameter
Applies to:
Main (window only)
Format:
true/false
Default value:
false

True if the window should be in fullscreen mode. This suppresses can-resize, titlebar, is-maximized, and is-minimized. They will continue to return the values that would apply if fullscreen mode were turned off.


is-list parameter (skin)

See also:
cells parameter
current-cell parameter
Applies to:
Grid
Format:
true/false
Default value:
false

True if the grid is used for a flexible list of items; the number of columns and rows may change to fit them.


is-maximized parameter (skin)

See also:
can-resize parameter
is-minimized parameter
is-fullscreen parameter
size parameter
outer-size parameter
Applies to:
Main (window only)
Format:
true/false
Default value:
false

True if the window is maximized.

If is-fullscreen is true, this value represents the state of the window when is-fullscreen is turned off again.


is-minimized parameter (skin)

See also:
can-resize parameter
is-maximized parameter
is-fullscreen parameter
size parameter
Applies to:
Main (window only)
Format:
true/false
Default value:
false

True if the window is minimized.

If is-fullscreen is true, this value represents the state of the window when is-fullscreen is turned off again.


is-pane parameter (skin)

See also:
id parameter
Child control
Tab control
Applies to:
Main
Format:
true/false
Default value:
false

True if this is a pane that will be used in other container controls, instead of an independent window. Read-only.


is-password parameter (skin)

See also:
command parameter
multi-line parameter
no-command parameter
Applies to:
Input
Format:
true/false
Default value:
false

Hide text with asterisks. Copy to clipboard is not available in this mode, but the text parameter can still read the control's contents.

Note: For obvious reasons, you should never use the same password in a game that you would use anywhere else.


is-slider parameter (skin)

See also:
value parameter
Applies to:
Bar
Format:
true/false
Default value:
false

Make this an adjustable slider capable of being changed by the user, instead of a progress bar.


is-transparent parameter (skin)

Applies to:
All
Format:
true/false
Default value:
false

Make this control transparent.

Transparency support is extremely limited. Only some controls can actually use it, and only when on top of certain other controls.

Bars and labels handle transparency reasonably well, when not on top of other controls (or only on top of other conrols of these types).


is-vert parameter (skin)

See also:
left parameter
right parameter
show-splitter parameter
splitter parameter
Applies to:
Child
Format:
true/false
Default value:
false

The splitter between the two panes in this control is vertical.


is-visible parameter (skin)

See also:
is-disabled parameter
Applies to:
All
Format:
true/false
Default value:
true

True if this control can be seen. The main window should usually be made visible.


keep-aspect parameter (skin)

See also:
image parameter
image-mode parameter
Applies to:
Label
Main
Format:
true/false
Default value:
false

If stretching a background image, preserve its aspect ratio.


left, top parameters (skin)

See also:
right parameter
is-vert parameter
show-splitter parameter
splitter parameter
Applies to:
Child
Format:
string
none
Default value:
none

The id of the left/top pane in this control. The parameter names left and top can be used interchangeably.


legacy-size parameter (skin)

See also:
font-size parameter
Applies to:
Output
Format:
true/false
Default value:
true

When true, font sizes are scaled slightly larger for readability, which is legacy (and default) BYOND behavior. Set to false for exact font sizing.


letterbox parameter (skin)

See also:
view-size parameter
zoom parameter
zoom-mode parameter
Applies to:
Map
Format:
true/false
Default value:
true

If map auto-scales its icons (zoom is 0), make sure the entire map fits, and fill excess space with the background color.

If letterbox is not enabled, auto-zoom will fill all available space, and any excess will be cut off.


line-color parameter (skin)

See also:
background-color parameter
show-lines parameter
Applies to:
Grid
Format:
#rrggbb
none
Default value:
#c0c0c0

The color of grid lines.


link-color parameter (skin)

See also:
text-color parameter
visited-color parameter
Applies to:
Grid
Output
Format:
#rrggbb
none
Default value:
#0000ff

The color used for links. In some controls visited links may have a different color.


lock parameter (skin)

See also:
left parameter
right parameter
is-vert parameter
show-splitter parameter
splitter parameter
Applies to:
Child
Possible values:
left
right
none
Default value:
none

Allows one pane to "lock" the splitter so if this Child control is resized, the splitter will stay put on that side.


macro parameter (skin)

See also:
Keyboard/gamepad macros
menu parameter
id parameter
Applies to:
Main (window only)
Format:
string

The id of the macro set this window will use, if any, when it's active.


map-to parameter (skin)

See also:
macros (skin)
command parameter
id parameter
name parameter
Applies to:
Macro
Format:
string

The macro name (e.g., "SOUTH") of a key combo, Dpad, mouse button, etc. that this macro maps to.


max-lines parameter (skin)

Applies to:
Output
Format:
number
Default value:
1000

Maximum number of lines before the control drops old text to make room for more. 0 is no limit.

An overflow of 5% is allowed, to reduce flicker.


menu parameter (skin)

See also:
macro parameter
id parameter
Applies to:
Main (window only)
Format:
string

The id of the menu this window will use, if any, when it's active.


multi-line parameter (skin)

Applies to:
Info
Input
Tab
Format:
true/false
Default value:
false: Input control
true: Info and Tab controls

Input control: Create a multi-line input control. Read-only for this control.

Info and Tab controls: Show tabs in multiple rows if there are too many to fit in a single row.


name parameter (skin)

See also:
macros (skin)
id parameter
Applies to:
Macro
Menu
Format:
string

Macro control: The key/gamepad combination such as R+REP, CTRL+Northwest, GamepadLeft.

Menu control: This is the menu item label. A tab character can be used between the name and a keyboard shortcut, like "Help\tF1". (Keyboard shortcuts must be implemented as macros in order to work. This is just a label.) A blank name shows just a separator.


no-command parameter (skin)

See also:
command parameter
is-password parameter
multi-line parameter
Applies to:
Input
Format:
true/false
Default value:
false

True if this input control is for typing only; hitting Enter will not run a command.


on-blur parameter (skin)

See also:
focus parameter
on-focus parameter
Applies to:
Input
Format:
string

Command executed when the control loses focus.


on-close parameter (skin)

See also:
can-close parameter
on-size parameter
Applies to:
Main (window only)
Format:
string

Command executed when the window is closed.


on-change parameter (skin)

See also:
value parameter
Applies to:
Bar
Format:
string

Command executed when the value of the bar/slider is changed. If you drag the slider around, the command will not run until you let go.

If you include [[*]] in the command, it will be replaced by the control's new value. (See "Embedded Winget" in client commands for more details on the [[...]] format.)


on-focus parameter (skin)

See also:
focus parameter
on-blur parameter
Applies to:
Input
Format:
string

Command executed when the control gains focus.


on-hide parameter (skin)

See also:
on-show parameter
Applies to:
Browser
Info
Map
Format:
string

Commandexecuted when this control is hidden by the game. Must be the default control for the game to show/hide it.

Currently not editable in Dream Maker.


on-show parameter (skin)

See also:
on-hide parameter
Applies to:
Browser
Info
Map
Format:
string

Command executed when this control is shown by the game. Must be the default control for the game to show/hide it.

Currently not editable in Dream Maker.


on-size parameter (skin)

See also:
size parameter
Applies to:
All
Format:
string

Command executed when this control is resized. If you are dragging a window edge or splitter, the command won't run until you finish.

No command will be sent in response to size or splitter changes made by winset().

If you include [[*]] in the command, it will be replaced by the control's new size. Likewise, [[width]] will be replaced with the width and [[height]] with the height. (See "Embedded Winget" in client commands for more details on the [[...]] format.)


on-status parameter (skin)

See also:
statusbar parameter
Applies to:
Main
Format:
string

Command executed when the text that would go in the statusbar is changed. This applies even if this control is a pane and not a window, or is a window without a statusbar. It applies to all panes and windows that directly or indirectly contain whatever control generated the statusbar text (e.g., a map).

If you include [[*]] in the command, it will be replaced by the new text. (See "Embedded Winget" in client commands for more details on the [[...]] format.)

[[from]] can be used to reference the control (if any) that generated the next text. You can also use expressions like [[from.type]], [[from.parent.pos.x]], etc.


on-tab parameter (skin)

See also:
current-tab parameter
tabs parameter
Applies to:
Info
Tab
Format:
string

Command executed when the current tab is changed.

If you include [[*]] in the command, it will be replaced by the new tab's id. (See "Embedded Winget" in client commands for more details on the [[...]] format.)


outer-pos parameter (skin)

See also:
pos parameter
outer-size parameter
inner-pos parameter
Applies to:
Main
Format:
x,y

Read-only.

Reads the control's current exterior position including titlebar, statusbar, borders, etc. If the window is not minimized or maximized, this is identical to pos.


outer-size parameter (skin)

See also:
size parameter
inner-size parameter
Applies to:
Main
Format:
widthxheight

Read-only.

If the control is a window, this refers to its current exterior size including titlebar, statusbar, borders, etc. If the window is maximized, this is the maximized size.

If this control is a pane and can-scroll is true, this is the size of the display area including the scrollbars.


parent parameter (skin)

See also:
id parameter
type parameter
name parameter
Applies to:
All
Macro
Menu
Format:
string

The id of this control's parent. Write-only, used when creating a new control at runtime or deleting a control that was created this way.


pos parameter (skin)

See also:
anchor1, anchor2 parameters
size parameter
Applies to:
All
Format:
x,y
none
Default value:
x,y
none

Position of this control's upper left corner, relative to its container. (Not applicable to panes.)


prefix-color parameter (skin)

See also:
text-color parameter
suffix-color parameter
Applies to:
Info
Format:
#rrggbb
none
Default value:
none

The color used for the prefix/header column of statpanel displays. No color means the default text-color will be used.

In BYOND 3.0, this color was red.


right, bottom parameters (skin)

See also:
left parameter
is-vert parameter
show-splitter parameter
splitter parameter
Applies to:
Child
Format:
string
none
Default value:
none

The id of the right/bottom pane in this control. The parameter names top and bottom can be used interchangeably.


right-click parameter (skin)

See also:
mouse handling
popup_menu setting (verb)
drop-zone parameter
Applies to:
All
Format:
true/false
Default value:
false

True if this control should allow right-clicks to behave like any other click instead of opening up popup menus or similar special behavior.


saved-params parameter (skin)

Applies to:
All
Format:
string
Default value:
varies

A semicolon-separated list of parameters that get saved with this control. This is often used for things a user might set, like zoom level for a map.

Currently not editable in Dream Maker.


screen-pos parameter (skin)

See also:
pos parameter
outer-pos parameter
Applies to:
Main
Format:
x,y

Read-only.

For windows, this is the upper left corner of the nearest monitor's area.


screen-size parameter (skin)

See also:
size parameter
outer-size parameter
Applies to:
Main
Format:
widthxheight

Read-only.

For windows, this is the size of the nearest monitor's area.


size parameter (skin)

See also:
pos parameter
anchor1, anchor2 parameters
on-size parameter
inner-size parameter
outer-size parameter
Applies to:
All
Format:
widthxheight

The size of this control.

Setting 0 for width or height uses up any available space right/downward.

If the control is a window, this refers to its interior size when not maximized or minimized. That is, it does not count borders, titlebar, menu, or statusbar, and if the window is minimized/maximized, this refers to the window's normal size when it is restored. See the inner-size and outer-size params for comparison.

If this control is a pane and can-scroll is true, size refers to the total scrollable size of the pane, NOT the smaller size displayed. In this case, outer-size and inner-size refer to the display area with and without scrollbars, respectively.


show-history parameter (skin)

See also:
show-url parameter
use-title parameter
Applies to:
Browser
Format:
true/false
Default value:
false

Show forward/back navigation buttons.


show-lines parameter (skin)

See also:
line-color parameter
Applies to:
Grid
Possible values:
none
horizontal
vertical
both
Default value:
both

Determines which grid lines to display.


show-names parameter (skin)

See also:
name var (atom)
small-icons parameter
Applies to:
Grid
Format:
true/false
Default value:
true

When atoms are output to the grid, show the atom's name next to its icon.

If the atom has no icon and show-names is false, the grid cell will be blank.


show-splitter parameter (skin)

See also:
left parameter
right parameter
is-vert parameter
splitter parameter
Applies to:
Child
Format:
true/false
Default value:
true

Show a splitter if both the left and right (or top and bottom) panes are in use. The splitter can be dragged to resize the panes.


show-url parameter (skin)

See also:
show-history parameter
use-title parameter
Applies to:
Browser
Format:
true/false
Default value:
false

Shows an address bar for this browser control.


small-icons parameter (skin)

See also:
show-names parameter
Applies to:
Grid
Format:
true/false
Default value:
false

When output(object,grid) is sent, show smaller icons in this control instead of larger ones.


splitter parameter (skin)

See also:
left parameter
right parameter
is-vert parameter
show-splitter parameter
Applies to:
Child
Format:
number (0 to 100)
Default value:
50

Position of the splitter when two panes are in use, whether show-splitter is true or not. This value is a percentage. Specifically, it is the percentage of the available width/height that is given to the left/top pane.


suffix-color parameter (skin)

See also:
text-color parameter
prefix-color parameter
Applies to:
Info
Format:
#rrggbb
none
Default value:
none

The color used for the suffix column of statpanel displays. No color means the default text-color will be used.

In BYOND 3.0, this color was blue.


statusbar parameter (skin)

See also:
titlebar parameter
on-status parameter
Applies to:
Main (window only)
Format:
true/false
Default value:
true

Shows a status bar at the bottom of the window. This will show the name of an atom when you hover over it with the mouse.


stretch parameter (skin)

See also:
image parameter
image-mode parameter
Applies to:
Label
Format:
true/false
Default value:
false

Stretch the background image. Deprecated; use image-mode instead.


style parameter (skin)

Applies to:
Grid
Map
Output
Format:
string

Custom stylesheet used for the control. Changes made at runtime will usually not impact any existing text.

For Map controls, this affects any maptext drawn, and changes to the style should appear on the next refresh.


tab-background-color parameter (skin)

See also:
background-color parameter
tab-text-color parameter
tab-font-family, tab-font-size, tab-font-style parameters
Applies to:
Info
Format:
#rrggbb
none
Default value:
none

Affects the background color for tabs. The regular background-color is used for the content area.


tab-font-family, tab-font-size, tab-font-style parameters (skin)

See also:
font-family parameter
font-size parameter
font-style parameter
tab-text-color parameter
tab-background-color parameter
Applies to:
Info

Affects the font for tabs. The regular versions of these without the tab- prefix are used for the content area.


tab-text-color parameter (skin)

See also:
text-color parameter
tab-background-color parameter
tab-font-family, tab-font-size, tab-font-style parameters
Applies to:
Info
Format:
#rrggbb
none
Default value:
none

Affects the text color for tabs. The regular text-color is used for the content area.


tabs parameter (skin)

See also:
current-tab parameter
id parameter
multi-line parameter
Applies to:
Tab
Format:
string

A comma-separated list of id values for the panes included as tabs in this control.

When setting this value, you can put + in front of the list to add tabs to the existing control, without affecting current tabs. You can likewise use - in front of the list to remove tabs.

Note: When using this with winset(), remember you will need to escape + as %2B via url_encode() or list2params().


text parameter (skin)

See also:
font-family parameter
font-size parameter
font-style parameter
text-wrap parameter
Applies to:
Button
Input
Label
Format:
string

Text shown in this control. For Input controls this setting is only available at runtime.


text-color parameter (skin)

See also:
background-color parameter
font-family parameter
font-size parameter
font-style parameter
Applies to:
All
Format:
#rrggbb
none

The control's foreground text color.


text-mode parameter (skin)

See also:
zoom parameter
zoom-mode parameter
Applies to:
Map
Format:
true/false
Default value:
false

Show text mode even if icons are available. Text mode will be used if no icons are present, regardless of this setting.


text-wrap parameter (skin)

See also:
text parameter
Applies to:
Label
Format:
true/false
Default value:
false

Wrap text that is too long for the width of the label.


title parameter (skin)

See also:
name var (world)
icon parameter
Applies to:
Main
Format:
string

The title of this window or pane. For a window, the title will appear in the titlebar if present. For a pane, this will be displayed on the tab if this pane is in a Tab control.

If this is the default window, world.name takes precedence over the window title.


titlebar parameter (skin)

See also:
can-close parameter
can-minimize parameter
can-resize parameter
icon parameter
title parameter
use-title parameter
statusbar parameter
is-fullscreen parameter
name var (world)
Applies to:
Main (window only)
Format:
true/false
Default value:
true

Show a titlebar for this window. This is also required for the close, minimize, and maximize buttons to appear.

If is-fullscreen is true, titlebar is ignored, so this value represents the state of the window when is-fullscreen is turned off again.


transparent-color parameter (skin)

See also:
alpha parameter
Applies to:
Main (window only)
Format:
#rrggbb
none
Default value:
none

A color that will be turned into transparency wherever it appears in this window. Overall, this method of transparency comes with many limitations, so it is considered deprecated.


type parameter (skin)

See also:
id parameter
parent parameter
Applies to:
All
Macro
Menu
Format:
string

The type of this control. Read-only.


use-title parameter (skin)

See also:
show-history parameter
show-url parameter
title parameter
titlebar parameter
Applies to:
Browser
Format:
true/false
Default value:
false

Use the browser's document title to override the title of the window or pane it appears in.


value parameter (skin)

See also:
is-slider parameter
dir parameter
Applies to:
Bar
Format:
number
Default value:
0

The "fullness" of this bar/slider, as a percentage.


view-size parameter (skin)

See also:
letterbox parameter
zoom parameter
zoom-mode parameter
icon_size var (world)
view var (world)
view var (client)
HUD / screen objects
Applies to:
Map (window only)
Format:
widthxheight

The size, in pixels, of the map after zoom has been applied.

For instance, if the client view has 10×10 tiles (this includes any extended tiles caused by HUD objects) and world.icon_size is 32x32, the map has a native size of 320×320 pixels. If the map has a zoom level of 2, then view-size will be 640x640.

With a zoom value of 0, which is the default for most projects, the actual zoom level is automatically determined by the size of the map control, the map's native pixel size as explained above, and the value of the letterbox parameter.


visited-color parameter (skin)

See also:
text-color parameter
link-color parameter
Applies to:
Grid
Output
Format:
#rrggbb
none
Default value:
#0000ff

The color used for visited links.


width parameter (skin)

See also:
dir parameter
is-slider parameter
Applies to:
Bar
Format:
number
Default value:
10

Width, in pixels, of the bar or slider. A value of 0 uses all available width.


zoom parameter (skin)

See also:
letterbox parameter
view-size parameter
zoom-mode parameter
Applies to:
Map
Format:
number
Default value:
0

Zoom factor for icons on the map. 1 means to show the icons at their original size, 2 is 200%, 0.5 is 50%, and so on. A value of 0 stretches to fit available space.


zoom-mode parameter (skin)

See also:
letterbox parameter
view-size parameter
zoom parameter
Applies to:
Map
Posisble values:
normal
distort
blur
Default value:
normal

Controls the way the map is upscaled.

normal
Preserves a pixelated look, but does some blending between adjacent pixels when the zoom factor is not an integer. This is equivalent to upscaling by the next highest integer, then downscaling.
distort
Uses nearest-neighbor sampling to upscale. This may look odd if the zoom factor is not an integer, since for instance some pixels might scale up to be 2 pixels wide, others 3 pixels wide. Some users prefer it anyway.
blur
Uses bilinear sampling to upscale. This will cause a blurry appearance if the zoom factor is high, but it may be desired in some cases.

Appendix

This section contains miscellaneous information that may apply to multiple vars or procs.

Byondapi
CSS attributes
HTML colors
Color space
stddef.dm file

Byondapi

See also:
call_ext() proc

Byondapi is a set of exported functions from BYOND's core library that can be used by external libraries that you call via the call_ext() proc. The purpose is to make interfacing with native code easier, and to allow external access to BYOND's functionality. Before this existed, all external calls had to use text strings to pass data back and forth, which was inefficient for many uses and very limited.

To build your external library with Byondapi, you have to include the byondapi.h header file that's included in BYOND's distribution. When compiling in Windows, you'll also need to link with byondapi.lib; in Linux, your makefile should link with byondcore.so from BYOND's own bin directory.

Simple BYOND types

For simplicity, BYOND defines some basic types and macros in byondapi.h. The one most relevant to you is u4c, which is an unsigned 4-byte integer. There's also s4c which is a signed integer, as well as simple 1-byte and 2-byte ints that use 1c and 2c (respectively) insteaed of the 4c suffix.

CByondValue struct

The main structure used to pass data back and forth is CByondValue. This mimics an internal structure in BYOND that holds values of all sorts: numbers, null, references to strings, references to objects and lists, and so on.

The exact functions used for interfacing with this structure are documented in byondapi.h.

The main tricky aspect of working with BYOND data is strings. If you need to get the contents of a string, you'll need to allocate memory for the character data and call Byond_ToString() to get a copy of the string. For converting character data to an internal string stored in CByondValue, you'll need to call ByondValue_SetStr().

Other function calls

There are many function calls available in Byondapi for interacting with the server. These include the ability to read and write vars, call procs, create lists, read and write from lists, and so on.

Most of these procs return boolean values: true if they succeed, false if not. In the event of a failure, you can call Byond_LastError() to get the error message.

In any functions that read data from lists, or read string data, they require the caller to allocate the needed memory for a copy of the string or list items. In these cases, the functions also take a u4c pointer for the length. If the return value is false and the length is set to zero, an error occurred. If the return value is false and the length is non-zero, the new length value is the required length of the array; the memory should be allocated and the function called again.

BYOND servers handle proc executin and the management of data in a single thread. If your library tries to call any BYOND server functions in a different thread of its own, the call will block until the server thread can handle it.

C++ wrappers

If you want to use the handy C++ wrappers and classes, you can include byondapi_cpp_wrappers.cpp and byondapi_cpp_wrappers.h in your library.

The ByondValue class is a wrapper around CByondValue that handles a number of operations for you. You can redefine the argv argument of any call_ext() functions as an array of ByondValue instead of CByondValue, but the return value should stay a CByondValue.

Example:

#include <string>
#include <byondapi.h>
#include <byondapi_cpp_wrappers.h>
#include <string>

extern "C" BYOND_EXPORT CByondValue merge(int n, ByondValue v[])
{
    ByondValue result;
    std::string merged, str;
    for(int i=0; i<n; i++) {
        v[i].ToString(str);
        if(str) merged += str;
    }
    result = merged.c_str();   // ByondValue's assignment operator takes care of everything
    return result;
}

There is also a ByondValueList wrapper class for the list structure.

The external function calls like ByondValue_CallProc() have C++ wrappers that use the C calls internally, but if an error happens they'll throw a ByondExtException for you to catch. This replaces the more cumbersome approach of checking if the return value is false and then calling Byond_LastError().


CSS attributes

DM-CSS is a subset of CSS, and only supports some kinds of selectors and attributes.

The following table lists all supported attributes, and whether they are supported in text output, maptext, and in other controls (labels/etc.) Other controls will often allow only one style for an entire unit of text. A checkbox in "Other" only indicates that some support exists in other controls, but it may vary by the type of control.

AttributeOutputMaptextOtherNotes
color✔️✔️✔️Alpha colors may not be supported in some controls.
background✔️✔️✔️In most cases, only applies to the entire text body.
background-color✔️✔️
background-image✔️
font✔️✔️✔️
font-family✔️✔️✔️
font-style✔️✔️✔️
font-weight✔️✔️✔️
font-size✔️✔️✔️
text-decoration✔️✔️✔️Limited to underline, overline, line-through, blink, and none. Support for each of these may vary depending on where they are used.
text-align✔️✔️✔️justify is supported in output and maptext.
vertical-align✔️✔️Limited to top, middle, and bottom.
text-indent✔️✔️
margin-left✔️✔️✔️
margin-right✔️✔️✔️
margin-top✔️
margin-bottom✔️
margin✔️✔️✔️
width✔️✔️Applies only to some elements such as images.
height✔️✔️Applies only to some elements such as images.
line-height✔️✔️Support in output control is limited; line heights less than 1 are not respected.
Only unitless numbers, percentages, or em units are allowed.
white-space✔️✔️normal, nowrap, pre, pre-wrap, pre-line
text-shadow✔️
-dm-text-outline✔️Custom attribute: Adds an outline to text. Values are in the form: width color style.
The style is either blank, or any combination of the sharp and square keywords (see Outline filter).

These pseudo-classes are allowed in some contexts, but they can only change the text color.

Psuedo-classOutputMaptextOtherNotes
:link✔️✔️✔️
:visited✔️
:activeCurrently not used, but future support is planned.
:hover✔️

HTML colors

See also:
rgb proc

Text colors may be specified by name or RGB value. The RGB color format uses hexadecimal numbers, with 2 hex digits each for red, green, and blue. These range from 0 (00 in hex) to 255 (FF in hex). In certain situations BYOND will also honor a fourth pair of digits for alpha.

#rrggbb
#rrggbbaa

It is also possible to use 4 bit values by using only one hex digit per color. The full 8 bit color is produced by repeating each digit. For example, #F00 (red) is the same as #FF0000.

The named colors supported by BYOND, and their corresponding RGB values, are listed in the following table:

black #000000
silver #C0C0C0
gray or grey #808080
white #FFFFFF
maroon #800000
red #FF0000
purple #800080
fuchsia or magenta #FF00FF
green #00C000
lime #00FF00
olive or gold #808000
yellow #FFFF00
navy #000080
blue #0000FF
teal #008080
aqua or cyan #00FFFF

Color space

See also:
rgb proc
rgb2num proc
gradient proc
animate proc
Color gradient
Color matrix filter

There are different ways of interpreting color besides RGB. Several parts of BYOND are capable of using other color spaces.

COLORSPACE_RGB

The default color space is RGB, where each color is split into red, green, and blue components, as well as an optional alpha. All of these components range from 0 to 255.

The color yellow for instance is rgb(255,255,0) which is red and green mixed together at their maximum brightness, but no blue component.

COLORSPACE_HSV

HSV stands for hue, saturation, and value.

All pure hues such as red (hue=0) have a saturation of 100 and a value of 100. As saturation decreases, the colors turns whiter. Lower values mean darker colors and darker shades of gray.

In HSV, saturation is less meaningful as value gets closer to 0. Black of course always has a value of 0. With 10 as the value, saturation=100 gives you a very dark color whereas saturation=0 is a 10% shade of gray.

COLORSPACE_HSL

HSL is a little more intuitive than HSV. Here, the value is replaced by luminance, which again ranges from 0 to 100. Luminance is the average of the minimum and maximum values of the red, green, and blue components.

Black has a luminance of 0; white has a luminance of 100. Pure hues all have a saturation of 100 and luminance of 50. As saturation decreases, the color will approach a grayscale shade of L%.

Saturation is less meaningful the closer luminance is to 0 or 100. At a luminance of 100, the saturation is totally irrelevant. At 90, high saturation will get you a very light shade of the hue but that isn't very far off from a 90% shade of gray.

COLORSPACE_HCY

HCY stands for hue, chroma, and the Y is for grayscale luminance. (Again chroma and Y range from 0 to 100.) This color space is based around the apparent brightness of each color according to a rough approximation of human vision.

Chroma is similar to saturation in that it determines how far from grayscale the color is. As chroma decreases toward 0, the color approaches a grayscale shade of Y%. What's different about HCY color from HSV or HSL is that at chroma=0 and chroma=100 the colors should appear equally bright. Pure red, therefore, has a hue of 0, a chroma of 100, and a Y luminance of only 29.9—roughly what red would look like in black & white with all the color leached out.


stddef.dm file

This is a special file that's included in all projects when you compile. It contains various constants, definitions of some built-in datums, and so on.

You can see the contents of this file by creating a new file in Dream Maker called stddef.dm. It will automatically be filled with the standard definitions.

The contents of stddef.dm may change with new BYOND versions. However an eye is always kept on backwards-compatibility.