307-314 Release Notes
These notes represent the features and fixes added in during a fairly comprehensive,
five month beta-test period. They are in reverse chronological order, with the newest
additions at the top.
Added email confirmation on new keys. A confirmation number is sent to the
supplied email address. This must be inputted back into the dialog box to create
the key. Hopefully this will cut down on the key spamming; if not, we can always
enforce a key limit now that we can track them by email.
Fixed: found a source of "jerked chicken" effects where movement of client.eye and
client.mob were not quite in sync. (Deadron, Lummox JR)
Fixed: Movement animations were lingering after a jump to different z levels.
The map editor now brings up the "Set Size" dialog when you create a new map.
Dream Maker now has a "Window" menu that gives a list of all of the files that
are currently open in your project. You can select a file in the list to navigate
to it. (Deadron)
browse_rsc() is now ignored when running in CGI mode, so that web
applications can be tested in Dream Seeker and use browse_rsc() to make
files available that would normally be accessed through the web server.
Added a third argument to client/SendPage(message,recipient,options). The
options are encoded in a text string as params2text() key=value pairs:
SendPage("Test","Dan","summon") //send a summon page
SendPage("Test","Dan","email") //send as email
SendPage("Test","Dan","email;subject=Try+This") //configure the subject
The "summon" and "email" toggles can be assigned to either 1 or 0, but the
default is 0 if they are not in the option text and 1 if they are, so you
generally don't need to specify any value.
Similarly, you can now choose to send out pages "as email", where they will
be forwarded to a user's email rather than sent to the pager if they have that option
set. If they are not accepting email-pages, the page will be sent out as a nonexpiring
page that will be displayed when they next boot-up DS. (normal pages expire after one hour).
The hub server now stores undelivered pages for a short period of time (one
hour). These pages get delivered when you hook up with the dantom via DS. For the
time-being, we have disabled the email-forwarding of pages since this is a less obtrusive replacement. We will probably end up making it an option when you send the page, since
it is more context-dependent than anything.
The client now polls the server for pages every so often, depending on your
connection. This means that you will now receive pages even if you are behind a
firewall. It is still better to configure the pager-port (which allows dantom to
contact your machine), since polling is slower and less efficient, but in some
situations it is the only option.
The icon editor now gives you an option to break up large images (>32x32) when
you import them. They will be broken up into individual tiles whose states are labeled
by their offsets in the image (eg: "2,2"). This is the same format used implicitely
by the server when icons are assigned to large .bmp or .png files.
The icon editor now uses color quantization when importing or pasting graphics.
This just means that it attempts to select the "best" set of colors when your image
exceeds the current 256-color limit. In previous releases, the editor would not change
the existing colormap if all of the cells were filled, so that if you imported a new
graphic that used drastically different colors, it would often give horrible results.
In the next major release of BYOND, we will update the color format to handle 24-bit
(true color), so that none of this quantization will be necessary. However, in practice
the current results are pretty good and this is considerably more efficient.
Fixed: images attached to invisible objects were not showing up. (Skysaw)
Fixed: typesof() was not working correctly on /atom and /atom/movable.
Fixed: Embedded links in files passed to browse() were occassionally failing to
When you receive a page and are not in the pager window, the pager tab will remain
highlighted (blue) until you toggle over to it. This only applies when you are electing
to receive pages in the pager window (the default option). (Rcet)
Added fexists(File). It returns true if the specified file exists. You could
always do this by checking length(file)!=null, but this is a lot more intuitive.
Added ispath(X). It returns true if X is a type path. It also has a
two-argument form that works similarly to istype(X,Y), allowing you to test if
a given type path is derived from another one:
ispath(new/obj/sword) --> 0
ispath(/obj/sword) --> 1
ispath(/obj/sword,/obj) --> 1
ispath(/obj/sword,/mob) --> 0
Changed the behavior of istype() so that it only works on objects and not on
type paths. Now if you do istype(X,/obj/sword), you will know for sure that
it is an /obj/sword object and not just a type path.
Fixed: A freeze-up was happening if a client suddenly disconnected right
while new resources were added to the server's cache.
Fixed: The default map placement in mob/Login() was sometimes causing very long
delays. This could happen either if there was a large region starting at
(1,1,1) that provided no place to land, or if mob/Move() was overridden and
failed to return a true value. It should now handle these cases much more
Movement of client.eye now scrolls the map in the same way as movement of
client.mob. Previously, the map always moved in jumps when client.eye to a
different location than that of client.mob. Now, if you move the eye one step
at a time, it will scroll the map smoothly. (Gughunter, Deadron)
Fixed: The deletion of multiple bookmarks at the same time was causing DS to
Fixed: The syntax coloring wasn't correctly handling preprocessor statements.
Fixed: Starting with the map disabled and then turning it on
(client.show_map=1) was crashing Dream Seeker. (Foomer)
Added the ability to hide verbs from the right-click menu:
set src in view()
set popup_menu = 0 //do not show in right-click popup menu
Added a few more options to browse():
clear=0 // set to 1 to clear the webbrowser history
display=1 // set to 0 to just send the file to the cache, rather than displaying it
file=name // specify the file name for the sent file (useful with display=0)
Note that the 'display' setting effectively replaces browse_rsc(), but we'll keep
that around too since it's shorter. One nice thing about this new setup is that you can
send html text to the cache without having to create a new file.
Added client.byond_version. It only spits out the main version right now
because we aren't technically tracking the sub-versions.
Fixed: Instances of /atom/movable were getting confused for instances of
/obj in for-loops over objects of type /obj. (Shadowdarke)
Fixed: When two identical icons were sent to the cache using browse_rsc(), the
second wasn't being saved. (Lummox JR)
Fixed: there was a good potential for stack overflows in the config code when
handling large config databases.
You can pass null to icon.SwapColor() to indicate the mask (Gazoot).
var/icon/I = new(usr.icon)
I.SwapColor(null,rgb(0,0,255)) // replace mask with blue
usr.icon = I
input() as command_text|... in list(...) now has the effect of suppressing
the popup dialogue so that the prompt appears on the command-line instead.
Access to resources from a locally hosted game should be faster now, because
the client and server now share the same memory objects used to access the
world rsc file.
Messages sent to browser windows (browse("message",...) clear the
browser history, so that users cannot navigate back using the arrow keys
or right-click context-menus. We can make this a browse() parameter
("clear=1") if there is any demand for the alternate behavior of caching the
messages. Note that URLS (link(), etc) are still cached, at least until a
browse() message clears them out. (Lesbian Assassin)
Savefiles used to immediately crash the proc when failing to open/lock a
file. It is now possible to supply a timeout and to do error checking without
getting a proc crash. This is most useful for CGI apps. Most games should
never have a locking problem, because only one instance of the game would
ever be running at a time. Example:
var/savefile/F = new(name,timeout) //open timeout
usr << "Failed to open file!"
if(!F.Lock(timeout)) //lock timeout
usr << "Failed to open file for writing!"
F.Unlock() //this happens automatically when the file is closed
In other words, savefile/New() takes a timeout as the second argument, and
there are two new savefile procs: Lock() and Unlock() for controlling
exclusive write access to a file. The return value is true if a lock could be
made; otherwise, if it is locked by somebody else or there are readers, it
will fail with a false value. A negative timeout makes it wait indefinitely.
If you do not call Lock(), a lock is automatically opened on the first write
operation. If a lock cannot be immediately obtained, this operation will fail
with a proc crash. The lock remains active until the file is closed or
Unlock() is called.
Trying to read from undefined variables at runtime was just silently
returning null. It now generates a runtime error, which is safer in the long
Calling undefined procs used to just silently fail, but it now generates a
runtime error. This affects situations such as this:
var/atom/O = someatom
O:someproc() // call someproc if O has it --> now an error if it doesn't
There are two valid ways to reorganize this code in a cleaner fashion. The first is
to make sure that the proc is defined for all objects that might use it:
atom/proc/someproc() // stub proc that does nothing by default
var/atom/O = someatom
The second is to check for existence of the proc before calling it:
var/atom/O = someatom
if(hascall(O,"someproc")) // make sure O has access to this proc
This and the changed behavior for undefined vars only affects
worlds compiled by version 311, since it is a slight backwards
Added the "enable HTML" option for pages. It is on by default. Turning it
off will cause pages to display in plain-text format. (Nadrew, Rcet)
Created a new option to show pages in a separate window (under the Pager
tab). The pager tab will blink when new pages come in, so you can check the window if
it is not already visible. This option is on by default-- you can go back to the old
style (where pages display in the main text) by using the Pager Preferences. (Theodis)
DS will now automatically execute in "debug mode" (deleting the byond.rsc and
turning tracing on) after it crashes. You'll be notified with a message box that
contains instructions to help us plug the problem, if it is reproducible.
Fixed: browse_rsc() on dynamically generated icons was not working correctly.
Dream Seeker was turning NUMLK off if it was enabled, due to some feature request
in the past. It now doesn't futz with the keys. (Scoobert)
Added a diagnostic tool for Dream Seeker. It's located in bin/debug.bat. It just
clears a few files and turns on a trace mode. Use this if you get any blue-screen or
other crashes occurring in byond.dll. Instructions are provided at boot-up ... basically
you just need to send us the trace.txt file that it generates.
Fixed: It was possible, without getting any compiler errors, to accidentally create
a data type with an empty name. (Sizzer)
Fixed: subscription data was not getting saved correctly in some cases.
(Xooxer, Shadowdarke, and many others)
Fixed: view() was behaving unpredictably when given a range outside of the
Fixed: the following code was adding to the user's contents list: (Foomer)
for(var/O in usr.contents + SecondList)
Entering a full URL into the Dream Seeker command line now causes it to
execute that URL. Previously, this only happened at the URL prompt, before
connecting to a game. A "full URL" is one that starts with a protocol such as
byond:// or http://.
Fixed: Found the source of a rare bug message: "Invalid obj..."
Fixed: The use of text icons was sometimes causing weird graphical glitches
(like transparent icons) elsewhere. Tell us if you still see this sort of thing.
Fixed: The "unexpected file transmission" problem. It was happening during
resource transmission when additional icons were created. (Lummox JR, Nadrew)
Fixed: Found the most likely cause of "zStream decompression failure". Since this
one was happening so infrequently, we'll have to wait for reports to confirm
that it is indeed fixed. Please report any BYOND BUG messages!
Fixed: Successive walk_X() calls on the same object were sometimes failing
to change the movement parameters. (AbyssDragon,FIREking)
Fixed: Tabs at the beginning of a line were being treated differently.
Fixed: Many worlds give special "host" powers to the first player to log in,
but rebooting the world was not guaranteed to log that person back in first.
It now makes everyone else wait (up to 30 seconds) until the first player
reconnects. It is probably not a good idea to ever give system-level powers
on the basis of login order alone, but merely giving host status is fine.
System-level powers could be granted when client.address is empty, indicating
that the person is directly running the game in DS. For remote users, an
appropriate mechanism is to check if their key is listed in
world.GetConfig("admin"), which is how Dantom.HostServer works.
Fixed: Tweaked a few UI elements to clean up some redraw problems on the map,
splitter bar, and browser.
Fixed: pick() was generating run-time error messages when passed a single non-list
argument. It now returns that value. (Theodis, Gughunter)
You can now
use "titlebar=0" to remove the title bar. You can also set the border size with
"border=X" (X in pixels). Example:
usr << browse("This is a mostly-empty box","window=empty;titlebar=0;border=0")
The window settings simply control the dialog box and space around the browser.
You can control the formatting of the content using html:
usr << browse("Let's get rid of those scroll bars!","window=noscroll")
You can even set the window's title through html:
usr << browse("HelloHello world!","window=hello")
Fixed: There were some file transmission problems where it was failing to
recover after a transmission error.
Fixed: The status bar and statpanels were sometimes displaying garbage characters.
Fixed: Found a longstanding bug that was causing corruption in the rsc
file. Also fixed a case where the cache code was crashing.
Fixed: Icons in the stat panels sometimes were redrawing incorrectly when the
cursor moved over them. (Zilal)
Fixed: Setting client.show_map=0 at runtime wasn't working. (Theodis)
Changed the "New Environment" dialog to make it a bit more intuitive. It now
separates out the directory and project name, and saves the last used directory
(eg: C:\windows\desktop) so you don't have to keep entering it in. Zilal, you might
want to update ZBT when we do the public release. The blurb in there about changing
the directory inspired this little change!
Fixed: image() now works on areas, in the stat panels, and on screen objects.
Fixed: sleeping in Entered() was causing crashes. (Kunark)
Fixed: Assignments to mob.see_infrared were producing run-time errors.
spawn(-1) now causes the spawned code to be executed immediately but in a
separate chain of execution so that if it enters into a sleeping state, the
caller resumes execution immediately. Not important--just letting everyone
know. Doing spawn(0) is similar, except the spawned code is queued for
execution and the caller continues uninterrupted.
Fixed: input() was getting hung up on empty possible value lists. (Nadrew)
Fixed: Resource files in libraries were not directly accessible from external
projects (you had to type out the full path to the library). Rebuilding the library
will fix this. (Deadron)
Fixed: Resource distribution was failing after sending out a large number of
batches of dynamically generated resources. (Gazoot)
Fixed: DS was generating "Download already in progress" on the next attempt after a
failed attempt to download a hub package.
Fixed: Dream Daemon was querying the user with an unnecessary popup box upon
Fixed: Reboot was resetting world.visibility and world.channel to their
default values. It now preserves the previous settings. (Leftley)
Fixed: The map-editor was occassionally crashing when you resized the map with
an active selection. (Xooxer)
Fixed: After a reboot, icons in the text panel were sometimes displaying the wrong thing. (Lummox JR)
Fixed: pager bans were causing Dream Seeker crashes in some cases. (Nadrew)
Minor interface change: when in macro-mode (ALT button down), the text in the
command-box is "(macro)" rather than ".alt". It seems clearer that way.
Added an option to make popup dialogs through the browse() proc. Consult the
entry for specifics.
Fixed: new() was returning without waiting for sleeping operations in New()
to finish. Make sure you are not ever entering an infinite sleep loop (ie a
"ticker" loop) in New() without spawning that off. If you do that, new() will
Fixed: With the pager running on a fixed port, multiple instances of DS were
conflicting with each other so that none of them could receive pager messages.
mob.see_invis can be set to 101, just like atom.invisibility, in order
to bypass the filtering of "super-invisible" objects from possible values
lists in verb arguments. In other words, if an admin needs to be able to see
super-invisible objects for low-level control of the game, it can be done.
Added atom.mouse_opacity. It has the following possible values:
0 //totally transparent to the mouse
1 //(default) clear parts of icon are transparent to the mouse
2 //no parts are transparent to the mouse
browse(null) now closes the browser.
An extra level of "absolute" invisibility (numerically 101) can now be used
to force an object to be stripped from all verb argument possible value lists.
Other invisible objects are no longer filtered out as they used to be, since
the normal behavior of view() now takes invisibility into account, and since
filtering in other cases was often unexpected. An example of a use for
absolute invisibility is a "verb container" object that exists purely as a
carrier of verbs and which should never ever be directly accessible to users
as a regular object.
Fixed: There was a memory leak in assignments of atom.icon to dynamically created
Fixed: When icon_state = "" and the icon file contained no such state, it was
sometimes displaying a random icon. (Nadrew)
Fixed: luminosity was still restricted to the range 0 to 7.
Fixed: A bug was causing the statpanels to sometimes show the wrong titles.
Fixed: Sometimes the stats weren't refreshing in a timely manner.
Fixed: Found the cause of the frequent "Security certificate"
failures. Forgot to randomize the random number generator in the client, so a
1 in 4 billion chance of picking the same old login cert id was quite a bit
less chancy. The garbage collection of old stale login certificates is now
handled as well, so a game with many different visitors will not have its
certificate database grow indefinitely over time.
Added PNG support everywhere. You can use them like BMP files (for incorporating in
worlds, saving as screenshots, etc), but they are much better! Besides being smaller,
they support transparency. Eventually we'll support the animated PNG format (called MNG),
but we'll at least wait for IE to catchup, since displaying such images in the
browser will probably be their main use.
DMI files can now be sent to the browser and displayed. (LummoxJR, Vortezz)
Internally, they are just converted to PNG format when they are stored in the cache/ directory. Example:
usr << browse_rsc('mob.dmi')
usr << browse("")
There are currently a couple of limitations in this system:
(1) The icon will display the default icon-state, or first one, if the default does
not exist. You can workaround this, though, by using the icon() proc to preselect
(2) Since BMP is a static format, animated icons will only show the first frame.
Added client.default_verb_category. All verbs with category = "" behave as
though they were assigned to this category. The default value is "Commands".
Setting this value to null would hide the default verb panel. (FIREKing)
Added client.perspective. The default value (0) is MOB_PERSPECTIVE, which
means visibility calculations having to do with opacity are done from the
point of view of client.mob, which is often what you would want when using
lazy_eye. Setting this value to EYE_PERSPECTIVE causes it to use client.eye
instead of client.mob.
Added mob.see_in_dark. This behaves just like mob.luminosity, except only
the mob itself can see this effect. The default value is 2, corresponding to
the old behavior in which even in a dark room with no light, the immediate
surroundings were always visible.
Added atom.infra_luminosity and mob.see_infrared. This is similar to luminosity, except it is
only visible to mobs with see_infrared=1 and it does not light up
anything other than the object itself, because, as everyone knows, infra-red
light does not reflect the same way visible light does.
view() now pays attention to the mob vision abilities. If you want an
"unbiased" view, do view(usr.loc) instead. Note that view(usr.loc) will
not filter invisible objects from the result, a somewhat subtle point
which is consistent with past behavior and documentation.
You can now do view(usr.client) to get a view list as seen by the client,
which might be different in cases where you have lazy_eye turned on.
atom.visibility is now being phased out in favor of atom.invisibility, which
has a range of 0 to 100. The corresponding variable mob.see_invisible
specifies the maximum level of invisibility that a mob is able to see. The
old mob.sight flag SEEINVIS is being phased out as well. Old dmb's will
continue to work as before, but the compiler will gripe on old code.
The verb visibility setting is also being phased out in favor of
"invisibility". The default behavior is for the verb to have the same
invisibility as the object to which it is attached. This variable, gives you
the power to create special "admin" verbs that are not visible to people who
can still see the object. Or you can create verbs which are visible but which
are attached to invisible objects. All this was possible before, using
visibility, but with only one level of invisibility, it was much less
Renamed mob.sight constants (retaining old ones for backwards
SEEMOBS --> SEE_MOBS //can see all mobs, no matter what
SEEOBJS --> SEE_OBJS //can see all objs, no matter what
SEETURFS --> SEE_TURFS //can see all turfs, no matter what
BLIND (same) //can't see anything
SEE_SELF (new) //can see self, no matter what
Added viewers() and oviewers(). These are like view() and oview(), except a
list of mobs that can see the center object are returned, rather than a list
of things the center object can see. For example, if you are standing in a
spotlight, people lurking nearby in the dark who you can't see, would still be
able to see you. (Or if you are in the dark and a creepy-crawly out there has
Added hearers() and ohearers(). These are like viewers() and oviewers(),
except lighting is not taken into account. For example, two people in a dark
room can hear each other but cannot see each other. At this time, opaque
objects block sound. In the future, other controls for sound transmission may
be added, along with mob hearing capabilities. However, even without those,
these procedures perform a function that was missing before, especially in
dark areas, where using view() would limit conversations to just people who
could happen to see each other.
Fixed: The compiler was generating badly messed up byte code on uses of invalid
variables inside procs with a declared return type. (Darkness)
Verbs can be hidden from the "command" panel by setting the category to
set category = null
Previously, this could only be done by "set hidden = 1", but that also caused
the verb to be hidden from the right-click menus and command-expansion.
Added isfile(). It returns true for any return value of file() and also for
items stored in the resource cache.
Removed the code that was setting usr.dir in client.Move(), since some time
ago, the code in atom.Move() was upgraded to handle facing obstacles anyway.
Added "freshness" detection to the config system. This should fix such
things as updating the compiler's list of libs when a new lib is installed
without rebooting the compiler. The user would still have to hit refresh, of
The map-editor now has the option to "Generate instances from directions". This
creates instances of objects whose icons are set to the various directions stored in
the DMI. For instance, you could apply the function to a directional wall and immediately
have access to the N, S, E, and W versions of that wall from within the editor.
Fixed: in lazy_eye mode, jumps in the eye position were often accompanied by
momentary blank patches on the edge of the map.
Added the following procedures to a new /icon object:
IconStates() // same as existing icon_states(icon)
Turn(angle) // same as existing turn(icon,angle)
Shift(dir,offset,wrap) // eg: Shift(NORTH,10,1); all pixels shift 10 to the north,
// wrapping around
Flip(dir) // eg: Flip(NORTH); mirrors icon about the horz axis
SetIntensity(r,g,b) // eg: SetIntensity(2,0,0); replaces the * icon operator
SwapColor(from_rgb,to_rgb) // eg: SwapColor(rgb(255,255,255),rgb(0,0,0)); white->black
Blend(rgb,function) // eg: Blend(rgb(255,0,0),ICON_ADD)); adds red to each pixel
Blend(icon,function) // eg: Blend('hat.dmi',ICON_OVERLAY); overlays hat.dmi
The Blend() operation supports the following function constants:
ICON_ADD // add the color or icon to each pixel of the source icon. In the
// latter case, the masks will be added as well. This is the same
// as the existing + and & arithmetic operations.
ICON_SUBTRACT // subtract the color or icon from each pixel of the source icon.
// This is the same same as the existing - operation.
ICON_MULTIPLY // multiply the source icon by the pixels of the color or icon. The
// transformation is: new_color = (new_color*old_color+127)/255
// for each of the r,g,b components of the color. This is the same as
// the existing * operation.
ICON_OVERLAY // overlay the color or icon onto the source icon. If a color is
// overlayed, a solid block of that color will result (ie- the
// source icon will be ignored). If an icon is overlayed,
// it will appear on top of the source icon.
There is currently no replacement for the arithmetical | operation, which
blends two icons and overlays the masks, but we suspect that the ICON_OVERLAY
operation will alleviate that need. If not, we can always add a function for it.
The advantage of the object based method of icon manipulation is that it is
directly modifiable in memory, whereas the old style operators often resulted
in extra loads from disk or at least copying of cached data in memory. When
doing a single-step operation, that doesn't make any difference, but when
doing multiple operations, this method is better.
The other advantage is that we are no longer constrained by the limitations of
trying to squeeze all of the icon manipulation functionality into a small set
of operators. Procedures may be added for any number of arbitrary operations,
and once a big enough base of functionality gets built up, soft-coded
procedures may be added to the /icon object or new types may be derived from
it in order to augment the built-in functions. Example:
var/icon/I = new('icon.dmi')
usr.icon = I
Icon objects should work in any function or assignment that can take icon files,
such as missile(), mouse pointers, and so forth. The one exception is that
currently the old-style icon arithmetic will not work with these icon objects, so
you should not mix the two styles. We are hoping that this new syntax will be able
to faze out the icon arithmetic operators because, aside from the incompatibility,
the old-style is more limiting and only has the advantage of being slightly
more compact and aesthetically pleasing.
Fixed: Map files in libraries were not getting packaged properly when generating a
source-code distribution. (Deadron, ACWraith)
Fixed: Invalid input in a popup dialogue that was not caught by the dialogue's only
built-in syntax checker was causing DS to get "stuck" so that all further
calls to input() just got silently queued up. (Nadrew)
View dimensions may now be specified as a text string in the form
"WIDTHxHEIGHT". For example, the default world.view is 5, which is equivalent
to "11x11". These types of values may be used with view(), oview(), range(),
orange(), and lazy_eye. The fact that it works with lazy_eye means you can
now make one dimension lazy and the other one strictly centered (e.g. "0x5"),
which could be useful for side-winding maps and the like.
Added client.view. By default, clients use world.view for the map size, but
you can override that at any point during the game.
Added icon(icon,icon_state,dir). You can use this to load the specified icon
state and direction from an icon file. If no state is specified, all states
will be included. Ditto for the direction. Eventually, the return value of
this procedure will be an /icon object, useful for manipulating icon data in
memory, but for now, you can just assign it to atom.icon and things like that.
Fixed: turf icons were failing to show up in the statpanels.
Added icon_x,icon_y arguments to MouseUp(), and MouseDown(). These indicate
the pixel coordinate within the icon (in the range 1 to 32) where the click
took place. The position 1,1 is the bottom left of the icon (southwest) and
the position 32,32 is the top right pixel (northeast). (various)
Added MouseEntered() and MouseExited() procs to the client and atom types.
These are only called when the mouse is moved with no buttons pressed. If only
a very small number of objects are sensetive to this event, it is quite a bit more efficient to define these on an object-by-object basis rather than globally on all
objects, or on the client object. (various)
Fixed: Libraries in Dream Maker were being included below the files that used
them, causing false warnings. They are now included first.
Fixed: sound(null,-1) wasn't properly halting the proper channel. (Air Mapster)
Fixed: The stat panels were occassionally failing to refresh. Fixed a few
more statpanel bugs and made the whole system update with less flicker too. (Cinnom)
Fixed: Some cpu-intensive worlds were causing the timers to get in a state of
limbo where certain things (like the map) didn't update properly.
Fixed: for(var/i = -5 to 5) and similar expressions were not working when the lower
bound was negative. (Gughunter)
Added icon_states(icon). It returns a list of text strings for the icon
states that exist in the given icon.
One good use for this is to automatically place large images (bmp files) on the map.
Each icon_state of a large image is automatically assigned to an "x,y" name
representing its coordinate-offset in the graphic, ie: "0,0", "0,1", and so forth.
You can use this information to perform some nifty placements without having
advanced knowlege of the graphics:
mob/verb/change_turf(turf_type in typesof(/turf)) // change my turf
var/turf/T = new turf_type(loc)
var/list/states = icon_states(T.icon)
// check for coordinates
for(var/state in states)
// look for "x,y" pattern
var/pos = findtext(state,",")
if(!pos) continue // not a coord
var/x_off = text2num(copytext(state,1,pos))
if(x_off==null || x+x_off>world.maxx) continue // not a coord or out of bounds
var/y_off = text2num(copytext(state,pos+1))
if(y_off==null || y+y_off>world.maxy) continue // ditto
T = new turf_type(locate(x+x_off,y+y_off,z))
T.icon_state = state
Added client.images, a list of images that are visible to the client.
Sending an image to a user via the << operator automatically adds to this
list. The main purpose of this list is to allow you to dynamically remove
images from the view of selected users without having to delete the image
Note that client.images is a specially allocated list. Each client has its
own independent list which cannot be pointed to some other list or anything
like that, just like atom.contents.
Added client/var/screen and atom/movable/var/screen_loc. This is a
mechanism with which one can display objects at fixed locations on the user's
display. You simply set the screen_loc and then add the object to the
client's screen object list.
The format of screen_loc is designed to be extendable in the future.
It is a text string that currently supports the following syntax:
"2,3" //numerical coordinates (x,y)
"3,11" //same as above with world.view=5
"3,NORTH+1" //directions with an offset
"3,12" //same as above when world.view=5
"NORTH+1,3" //when using directions, x and y are interchangeable
"NORTHEAST" //this short-hand is ok
"NORTH,EAST"//same as above
It also supports ranges to fill in square regions:
"SOUTHWEST to NORTHEAST" //covers entire map
"1,1 to 11,11" //same as above with world.view=5
Don't like the black background color of the map that shows through when
regions are out of sight? Simply create a screen object at a drawing layer
below all other map objects, set its location to the full range of the map,
and choose whatever color you want.
Notice that in one of the examples above, it set y=NORTH+1, which falls
outside of the map view. This is known as a "border" object. You are allowed
to create borders of any size as long as the full size of the inner map plus
border is within the 21x21 maximum size. Since these objects do not cover up
any part of the map, this is good for graphical controls such as toolbars,
indicators, and the like.
Screen objects obey the normal layering rules, so you can make screen objects
that overlay or underlay the objects in the map (or something in-between,
which would be odd).
One nifty way to create the client.screen list would be to design the screen
in the map editor. At run-time, you could add the objects from the map into
each user's client.screen list. That works out particularly nicely with tiled
bmps, since the map editor lays it all out for you. Just make sure you use
objs or mobs and not turfs or areas, since screen_loc is only defined for
atom/movable. We'll probably make a library for this in the near future.
Since screen objects can serve as the source of verbs, adding objects to this
list (even with screen_loc="") would be a convenient alternative to dynamic
modification of client.verbs. To make the verbs accessable, just do "set src
= usr.client.screen", replacing "=" with "in" if you want the other style of
It should be mentioned that unlike objects in atom.contents, the same object
may be placed in multiple client.screen lists. There is nothing special about
the screen list. Multiple clients may even use the same list.
Fixed: client.show_verb_panel was unnecessarily read-only at runtime. (Spuzzum)
Fixed: A glitch in the icon loader was causing occassional icon corruption. (various)
Fixed: Dream Maker's help system was freezing up on symbols that returned no results.
Fixed: Occassionally icons output in text were showing the wrong state. (Spuzzum)
Fixed: The maximum "hop count" (number of redirections while accessing a URL in
Dream Seeker) was too low to accomodate some insane libraries with many
You can now set image.dir dynamically. Note that you can also set it when
you create the image: new/image('blah.dmi',loc=X,dir=NORTH). (LummoxJR)
Added more resource optizations both avoid memory overflow with lots of
icon-arithmetic and to keep the cache from loading slowly. Icons should also display more
quickly in certain situations now.
The host-daemon settings (port, visibility, security) are now saved between sessions.
More sweeper optimizations. Statements such as "del X" were still invoking
the sweeper, even when the only remaining reference was the variable X itself.
It now explicitly clears the value of X before doing the deletion, because
that is a much faster operation. This works with either a variable or a list
item, such as List[i].
DM now accepts the following syntax:
for(i = 1 to 3) ...
It was already supporting it like this:
for(i in 1 to 3) ...
but if you forgot and used '=' instead of 'in' it was silently doing the wrong
There is now an "invite" option when you send a page to another user. This will
allow them to join you at your current location, even if it is invisible.
When a world is being hosted in DS, you can disallow new users from connecting
by reopening the "Host..." dialog and selecting that option. Users who are currently
connected will be unaffected.
Fixed: The code-editor's syntax-coloring scheme had some minor foibles. (Vortezz)
Fixed: Logging out of a world should no longer disconnect the pager.
This was only intended to disconnect the pager when you switched from one key
to another, which is what it does now. (Nadrew)
You can now set the server-safety level (trusted, safe, ultrasafe) from the
Improved some of the interface elements in the pixmap and map editors. (FIREking)
FILE_DIR now accepts quoted values, so that special characters such as
unbalanced quotes may be inserted in the path. The contents of the quoted
text should be escaped in the normal way, so \ must be \\ and so forth. The
automatic FILE_DIR generation now uses this, so paths with such characters in
them now parse properly. (Lord of Water)
Optimized the loading and drawing of icons, such as would
occur via icon arithmetic. Actually, resources in general should be stored and
accessed much more efficiently now. (Leftley, Lummox JR)
Turned on the sweeper optimization that assumes the reference count is
accurate and therefore aborts a sweep after finding as many dangling
references as were expected. There are still many sanity checks in place that
do not suck the cpu too much, so we will just have to rely on those to detect
problems out in the field. Object deletion could still be improved, but it
should be quite a bit faster in cases where there are few dangling references.
The worst dangling references to clean up are references from a turf variable
to an object that is getting deleted, when the map is really big. The turf
contents list is no problem; I'm talking about a user-defined turf variable
that points to an object that you delete without first removing the reference.
As a last resort, the sweeper ends up scanning through the whole map in order
to find the dangling reference. Still, this is way better than not having a
sweeper at all, considering the horrible sorts of errors that can occur with
Fixed: if no DM libraries were installed, Dream Maker was confusing the
environment file for a library. (Nadrew)
Fixed: Switching from one key to another in the same instance of Dream Seeker was
causing the new key to be attached to the old key's pager. (Sariat)
Fixed: client vars were not getting properly re-initialized after rebooting a game
in Dream Seeker. (Shadowdarke)
Fixed: The first frame of a flick was being skipped. It should now account for the
Fixed: When switching mobs, access to objects in the previous inventory was
sometimes still being allowed (specifically when the new inventory was empty).
Fixed: Missiles were not working outside of (1,1) --> (25,25)! (FIREking)
Optimized some icon display operations. When lots of icons were being generated and
written to the cache, the map was sometimes failing to update. This is still often the case-- it's
not perfect yet-- but there should be some improvement. (Leftley)
Fixed: Proc crash diagnostic messages were reporting zero-based turf coordinates
rather than the standard 1-based coordinates. (Sariat)
Fixed: for(var/list/L in X) was not working. (Air Mapster)
Fixed: The animation speed was off by 1-tick, making each movie play a bit too
slow. (Spuzzum, Air Mapster)
Fixed: The "as message" input boxes were appending an extra " character to
the output string. (Nadrew)
Fixed: Dream Maker's text undo mechanism wasn't working intuitively in all
situations. If you find any more quirky cases, please report them. (Skysaw, Air Mapster)
Fixed: Dream Maker's "Save As" option was not working properly for files in
You can now set the background color in the pixmap editor by clicking on the palette
with the right-mouse button. You can draw with it by clicking on the canvas with
the right-mouse button. (Rcet)
More pix: CTRL+Click is now a shortcut for the "Locate" color operation. (LummoxJR)
More pix: When you edit a color in the palette the default "custom colors" will be
initialized with the colors in the vicinity, so you can easily copy and group colors.
You can now use the arrow keys (along with various other hidden shortcuts) to navigate
between cells in the various grid controls (ie- the "pending map errors" dialog, the
instance editor, and so forth). (Gughunter)
The DS and DM (map-editor) popup menus now show object icons. Ooooh! (Gughunter)
The default channel (BYOND.Live) used to be hard-coded into the software,
but that has been replaced with a setting "default" that causes the world to
go live in all channels that the world is published in (and that the user has
access to, of course).
When you ban people from the pager, they are now automatically entered into
cfg/keyban.txt, a list of users who are blocked from connecting to games you
Since some games might want to handle banned users specially (silent bans), a
new world proc has been added called world/IsBanned(key,address). If this
returns a false value, then the user is allowed to log in. The default behavior is to return null unless the user is listed in cfg/keyban.txt. Consult the new
release notes for more info on the return code.
Added a new configuration set "ipban." It works similarly to "keyban"
except it matches the user's IP address rather than the key. Partial IP
addresses may be specified.
Added a record of the last IP address a banned user attempted to connect
from (stored in the keyban file). Currently, there is no built-in
functionality to make use of this information, but it could be useful in
determining whether an IP ban may be necessary/effective.
Fixed: DS was crashing on scripts with badly terminated STYLE blocks.
Fixed: Very long text strings in proc arguments were crashing the server if the
proc crashed. (Air Mapster)
Fixed: In DS, popup dialogs for arguments after a file or text argument that was
unterminated on the command-line were not building the command correctly.
Fixed: flick() was not working with an image as the first argument. Also,
switching to text mode and then back to icon mode was causing some flicks to
be dropped. (Air Mapster)
Fixed: alert() was displaying garbage characters when given a message or title
containing \improper. (Spuzzum)
Fixed: Errors including .dms files in a project were getting improperly displayed.
Fixed: There was a garbage collector bug message triggered by the use of mob
prototypes with hard-coded keys. (Theodis, Zilal)
Fixed: Another garbage collector bug message was triggered by an object referenced
by a verb argument getting deleted within that verb. (Zilal.Sixes)
Fixed: The movie-editor's dir-selection box was acting a bit quirky. (Air Mapster)
Fixed: The icon and movie-editors were not relaying keyboard commands in certain
Fixed: The icon-editor was sometimes claiming that files were modified when they
Fixed: (maybe) A weird graphical glitch was occurring when icons with lots of states
were loaded into the editor. (Shadowdarke)
Fixed: Dream Maker wasn't correctly creating new files in root directories. (Gughunter)
Added a 16x16 preview mode to the icon-editor. (Shadowdarke).
Added a preference to suppress the auto-generation of FILE_DIRs for every
subdirectory in the project. The Build/Preferences are saved on a per-project basis, but
whenever you change them the new settings will be used as defaults for all future
projects. (Air Mapster).
Fixed: Expansion of file names on the command line was not working correctly for
files in the working directory. (Air Mapster)
Fixed: findtext() was not working for text strings longer than 65535 characters.
Fixed: copytext() was hogging memory when copying small portions from large text
strings. (Air Mapster)
Fixed: Map files were not respecting FILE_DIR definitions. (Deadron)
Added ascii2text() and text2ascii(). Currently, character values are
limited to the range 0 to 255. Character value 0 terminates text strings, so
if you insert it into some text, everything after it will be truncated.
ascii2text(65) == "A"
text2ascii("A") == 65
text2ascii("HAPPY",2) == 65
Fixed a bug in the config system that was causing some trouble connecting to
games hosted offline in DD. This might also explain the occasional
passport subscription problem.
Fixed: time2text(world.realtime,"YY") was producing "101" instead of "01".
Fixed: downloading a key from the hub over one stored locally in the key
file (typically with a forgotten password) was not working.
Fixed: four-directional icons on objects with the same movement history were
not always appearing with the same orientation. This was happening when one
object went off-screen while the other remained on screen and they both made a
straight movement parallel to the map boundary and then a diagonal movement
back onto the map. If you see any more such behavior, please report, because
we believe this was the only possible source of mixed up directions. (Deadron)
Fixed: Deleting instances in the map editor sometimes crashed the program.
Fixed: The icon editor's copy/paste routine wasn't always working properly.
Now all worlds installed in MyHub (ie downloaded and installed from the hub
by DS) are automatically run in safe mode, whether they are in a self-named
directory or not.
You can now delete files in your project. Just right-click on the file-tree and
select 'Delete'. (Spuzzum)
The map editor has a new "Layers" menu. This can be used to specify which objects
are selectable (for move/cut/copy/paste operations). It can also be used to selectively
toggle the display of the different object types. (Deadron)
Fixed: Initialization of built-in variables was getting messed up when a
user-defined variable was defined with the same name at a higher level of
Added atom/movable/var/animate_movement. The default value is 1. Setting
it to 0 causes movement of the object to occur in discrete jumps between map
locate() now scans for derived types, rather than only an exact match. For
example, locate(/obj) could return an instance of /obj/sword. (Alathon)
DreamSeeker now parses quotes in user input better. It no longer gets
confused by such things as:
say "I am very "happy" to see you!
The parser can still handle termination of a quoted text argument; it just
handles nested quotes in a natural way. For example, the following will not
produce an extra terminal quote in what gets sent to the server:
say "I am very "happy" to see you!"
Added a new input type called "command_text". This takes exactly what the
user types from that point on in the command. The user's input can start with
a quote and it can contain \ characters. No special meaning is attributed to
these, nothing will be altered or translated, and no popup dialogues will be
generated. The intention is to support verbs that accept a command in some
alternate syntax (such as a natural language) with no interference whatsoever
from Dream Seeker. If you want to accept an empty input value, use
Fixed: The "Advanced Find/Replace" dialog was not providing all accessible options
on successive calls. (Zilal)
Fixed: Deleting hubfiles was sometimes crashing DS. (Lord of Water)
Fixed: Deep (or infinite) recursion was often not getting caught before the OS
killed the application due to shortage of stack space. This has been
improved. (Incidentally, this also eliminates the unadvertised maximum
limitation of 100 args in any procedure call.)
Fixed: savefile.ExportText() and ImportText() were not correctly handling escaped
characters within text strings. Also, savefile buffers starting with a number
were not being parsed correctly in ImportText(). In fact, any special
characters in savefile buffer names were producing parse errors in
Fixed: There was a little compiler glitch where the initial value of variables was
sometimes slightly wrong. If you defined a variable by the same name in
several different parts of the source code and initialized to 0, "", or null
in different cases, an internal optimization gone awry was initializing all of
these variables to just one of those values, which could produce unexpected
behavior in cases where the code depends on the difference between these
Added world.byond_version. This indicates the software version at run-time.
(The compile-time version was and is in the constant DM_VERSION.)
Added world.system_type. The system type is one of the following constants:
The shell() instruction can now be used with no arguments to determine if
the current safety mode allows shell() to be run. It returns true if in
trusted mode (in DreamDaemon) or if running in DreamSeeker (where it can ask
for permission to execute commands even in -safe mode).
Added a /zipfile object type. The interface is currently defined in an
optional library (Dantom.Zipfile). This object allows DM code to import or
export files from a zip archive.
world.OpenPort() now accepts a port parameter. Previously, it always picked
a port dynamically. In addition to opening a fixed port, it is also possible
to turn off the server port by calling world.OpenPort("none").
world.Export() now supports the http protocol using the HTTP GET method (no
post operations yet). 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:
var/http = world.Export("http://www.byond.com")
usr << "Failed to connect."
usr << "HTTP Header:"
for(var/V in http)
usr << "[V] = [http[V]]"
usr << "\n"
var/F = http["CONTENT"]
usr << html_encode(file2text(F))
"Export" is a bit of a misnomer, since a GET operation is generally used to
retrieve rather than send data. Of course, the URL may refer to a CGI
application, and you can communicate with it via the URL parameters, so this
is not strictly limited to information retrieval. In the future, full POST
support will be added.
You can now compile with client/preload_rsc assigned to a web URL pointing
to a zip file containing the .rsc for your game (or you can put the individual
icons and sounds directly in the zip file). This file will be automatically
downloaded by players when they connect for the first time. The point of this
is to reduce the network load on the machine serving the game. Example:
client/preload_rsc = "http://my.website/mygame_rsc.zip"
This file is cached so if you make big changes and want all players to
re-download the file, you should choose a new name to force a refresh.
Otherwise, it is assumed that new versions of the file (with the same name and
location) should not be downloaded again, because most of the contents would
be redundant. Resources that are not found in the preloaded .rsc will simply
be retrieved directly from the game server, so you don't have to worry about
keeping the web rsc package strictly in sync with the current version of your
game. It's just there to take the brunt of the bandwidth hit. In fact, you
could get fancy and only preload selected files.
If you are testing this out, note that the preload_rsc URL is ignored by DS
when you connect from the same machine as the game server. Also note that
unlike dynamic downloading of resources from the game server, there is no
provision for filtering out unwanted file types. For example, if a user has
sound turned off, sound files would not be downloaded from the game server,
but the preload package is all or nothing, so if it happens to contain sound
files, these will get downloaded along with everything else. This is probably
acceptable in most cases.
As an additional optimization, if DS has ever installed a game from the hub,
it will access the installed .rsc directly, rather than downloading resources
that it already has. This doesn't make much difference for games that
automatically preload resources, since the client will probably already have
them installed in the main cache (byond.rsc), but for games that do on-demand
resource loading, this will result in faster access for users who have already
installed the game.
Fixed: The compiler was failing to allow overriding of procedure properties when it
found a user-defined variable by the same name. (Foomer, Zilal)
Fixed: Verbs containing matching words (like Light() and Show_Light()) were
conflicting when used from the verb panels in cases where the longer of the
two had an implicit source and the shorter one had an explicit source. (Flick)
Fixed: Very old routing info in cfg/hosts.txt is now being automatically removed to
avoid conflict with byond://Key URLs used to "follow" friends. (Spuzzum, Gughunter)
Fixed: Error messages during the Login process were displaying in the wrong place.
Fixed: rand(-10,0) was returning only -9 to 0.
min() and max() can now take a single list as an argument and they will
operate on the items in the list. These instructions have also been upgraded
to work with text strings as well as numbers. Note that you can now use
arglist() with min() and max(), but it is equivalent to simply passing the
pick() also supports a single list as an argument. It returns a random
choice from the list.
image() now supports named arguments, and a number of new optional
parameters (just 'icon' and 'loc' existed before):
All but the first argument are optional. An image can be used as an overlay
or as the "icon" in a call to flick(), image(), or missile().
overlays += image('shirt.dmi',icon_state = "red")
The same thing could be accomplished before by creating a dummy object,
assigning its vars, and then creating an image from that.
One difference from before is that 'layer' is now respected for images.
Previously, images were always drawn in FLY_LAYER, regardless of the layer
setting applied to the source object used to create the image. If you were
creating images from objects, make sure the layer is set to what you want.
Images created from icon files are still drawn in FLY_LAYER by default.
The image() instruction is now a short-hand for new/image(). In other
words, there is now a type named /image. This allows you to move existing
images around and even modify their appearances dynamically.
The /image type looks a lot like /atom/movable, but it cannot be placed inside
of another object and it lacks any "physical" properties such as density.
Previously, these objects could not be written to savefiles, but now they are
savable like anything else.
The missile() instruction now also respects the layer of the source object,
rather than just drawing the missile in FLY_LAYER. If that's not what you
want, one way to override it is to use image():
usr << missile( image(spear, layer=FLY_LAYER), usr, target)
Previously, missile() did not show overlays/underlays, but now it does.
sound() has a couple of new optional parameters (and it now supports named
repeat: 0 to play once, 1 to play repeatedly (same as before)
wait: 0 to interrupt sounds playing on the current channel, 1 to wait for them to finish
channel: 0 for any available channel, 1-8 for fixed channels (wav only)
Note that midis can only play on a single channel (channel=-1) and that not all wavs
are mixable. Example:
usr << 'song1.mid'
usr << sound('song2.mid',wait=1) // wait for 'song1.mid' to finish
usr << sound(null,-1) // silence all midis
In addition, there is now a /sound datatype. Calling sound() is equivalent to
new/sound(), so you can store the return value and use it any number of times.
Previously, the sound() instruction always had to be used directly in an
Note that after outputting a sound, deletion of the sound object has no
audible effect. If you want to terminate a sound, you must do
sound(null,channel=X), where X is 0 to stop all sounds, or 1-8 to stop sounds
on a particular channel.
Optimized the sound mixing a bit, and added an option to toggle it from the
client (Preferences-->General). If a client doesn't use mixing, only a single midi
and a single wav can be played at the same time, equivalent to reducing the number
of wav channels to 1.
Sound files (.mid, .midi, .wav) are now displayed in Dream Maker's file
tree without the need for the "show all" box to be checked.
Added fcopy_rsc(file). This copies a file into the .rsc file and returns a
reference to the cached item. It is used internally by the DM code for
sound() in stddef.dm so that a sound object that happens to use an external
sound file may be effeciently used multiple times. Note that multiple calls
to fcopy_rsc(file) will return the same value, and the return value of
fcopy_rsc() (ie a cache file) will pass through fcopy_rsc() without
Clock skew is now detected and the user is warned. This has been causing
authentication failures on machines where the clock was way out of whack.
DM now recognizes a larger class of expressions when initializing object
variables. The most important advance is the ability to use new(). Example:
obj/my_obj = new()
You can also pass arguments into new().
All of this applies to the values of variables in the map object editor too.
Also note that the new expression handler for object variable
initialization is recursive. In other words, any expression that is allowed
can also be used as a parameter to another expression such as an item in a
list or an argument to new(). Previously, this was not the case.
306 Release Notes | View All