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.

b49 (314)

  • 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. b48

  • 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. (Lummox JR)

  • 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. (Shadowdarke)

  • Fixed: Embedded links in files passed to browse() were occassionally failing to work properly.

  • 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 efficiently.

  • 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 crash. (Gughunter)

  • Fixed: The syntax coloring wasn't correctly handling preprocessor statements. (Nadrew)

    b41 (312)

  • 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: mob/verb/test() 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). Example: 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. (Foomer)

  • 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 if(!F.name) usr << "Failed to open file!" return if(!F.Lock(timeout)) //lock timeout usr << "Failed to open file for writing!" return ... 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 run. (Gughunter)

  • 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 O.someproc() 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 O:someproc() This and the changed behavior for undefined vars only affects worlds compiled by version 311, since it is a slight backwards incompatibility.

  • 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. (Lummox JR)

  • 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 maximum 21x21.

  • 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. (Dreq, LummoxJR)

  • 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. (Zilal, Foomer)

  • 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("<body scroll=no>Let's get rid of those scroll bars!</body>","window=noscroll") You can even set the window's title through html: usr << browse("<head><title>Hello</title></head><body>Hello world!</body>","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. (Shadowdarke)

  • 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 closure. (Dreq)

  • 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 browse() reference 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 not return.

  • 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 icons. (Spuzzum)

  • 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. (Foomer)

  • 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: mob/verb/showDMI() usr << browse_rsc('mob.dmi') usr << browse("<img src=mob.dmi>") 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 particular states.
    (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 flexible.

  • Renamed mob.sight constants (retaining old ones for backwards compatibility): 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 infravision...)

  • 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 null: 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. (ACWraith)

  • 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 course.

  • 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. (Gughunter)


  • 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: New(file,state,dir) 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') I.Turn(90) I.Blend('icon2.dmi',ICON_ADD) 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. (LummoxJR)


  • 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 altogether.

    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,NORTH" //directions "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 syntax.

    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) b13

  • Fixed: Dream Maker's help system was freezing up on symbols that returned no results. (Dog Man)

  • 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 dependencies. (Gughunter)

  • 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 thing.

  • 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 "Host..." button.

  • 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 dangling references.


  • 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 delay. (Leftley)

  • Fixed: When switching mobs, access to objects in the previous inventory was sometimes still being allowed (specifically when the new inventory was empty). (Zubul)

  • 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 subdirectories. (Gughunter)

  • 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. (Gughunter)

  • 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 host.

    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. (GateGuardian)

  • 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. (Air Mapster)

  • 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. (Alathon)

  • 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 situations. (Spuzzum)

  • Fixed: The icon-editor was sometimes claiming that files were modified when they weren't.

  • 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. (Air Mapster)

  • 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. Example: 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". (Shadowdarke)

  • 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. (Kunark)

  • Fixed: The icon editor's copy/paste routine wasn't always working properly. (Gughunter)

  • 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 inheritance. (Zilal)

  • 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 positions. (LummoxJR)

  • 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 command_text|null. (Zilal)


  • 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 ImportText(). (Spuzzum)

  • 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 values.

  • 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: MS_WINDOWS UNIX

  • 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: 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)) "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. (Foomer)

  • 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 list directly.

  • 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): image(icon,loc,icon_state,layer,dir) 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(). Example: 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. image/var text icon icon_state dir layer overlays underlays loc x y z 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 arguments): sound(file,repeat,wait,channel) 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 sleep(100) 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 output statement.

    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 modification.

  • 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: mob/var 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