User Tools

Site Tools


An Introduction to Scripts

By Nameless Voice

A script in Dark is a piece of code that is placed on an object to do something when certain things happen to that object. Scripts are stored in script modules (.osm files), which are basically a library of classes and functions written in C++ and compiled into a dynamic-linked library (.dll). You need to load the script module file into your mission (using the script_load command) before you can use any of the scripts that it contains. All players must also have this script module for the scripts to work. You can either include the script module in your mission .zip, or instruct players that they need to have it installed in order to play the mission.

Scripts are placed on objects via the S→Scripts property.

Scripts are basically event handlers for events created by the game or by other scripts. Event handling in Dark works by means of script messages – special messages that are sent to objects by the engine when certain events occur. An example of this would be the FrobWorldEnd message, which is sent to an object when the player frobs that object in the world1).

Whenever an object receives a script message, it is passed to each script on the object in turn, starting from the script named in the Script 0 box on the object, then on through to Script 3, and then (unless the Don’t Inherit flag is set) it will go backwards up the inheritance tree until it reaches the base Object (-1), or encounters a script property that does have the Don’t Inherit flag set. Each of these scripts can then react to this message in whatever way they wish.

The Dark Engine exposes a set of functions that scripts are able to use to interact with the game world, such as retrieving or setting properties, creating and destroying objects or links, sending script messages, starting timers, and so on. While most of these systems are fairly versatile, the scripts are still limited in that they can only interact with the game world via the systems that Dark exposes for them. While custom scripts can do anything and everything that the standard scripts do, bear in mind that in some cases the engine may only allow them to do the exact same thing, rather than to do it slightly differently. An example of this would be the bow-drawing function. Basically, the arrow script tells the engine “Bring out the bow and use this object as an arrow”. A script couldn’t, for example, create its own type of weapon (say, a crossbow) for the arrow to be equipped in, since the engine handles the entire process of player arm creation and bow control. All the script can do is to tell it to equip an arrow. Of course, scripts can also do anything else you would expect a program to be able to do, such as perform calculations and logic on property values and then modifying them as a result.

A very important point is that scripts can send messages to other objects. For example, the StdButton script will send the message TurnOn down its ControlDevice links to any linked object. A lot of the standard scripts will respond to the TurnOn message by activating themselves – for example, a door (StdDoor) will open, a light (AnimLight) will turn on, and an emittertrap (TrapTweqEmit) will fire. Many of these scripts will also respond to the TurnOff message by deactivating. There is no special meaning to these two messages (TurnOn and TurnOff) – rather, they are a standard interface that was used by Looking Glass when the made the scripts. Technically, the messages could as easily have been named ”Bob” and ”James”, and as long as all the scripts were written to work with these messages instead, it would have made no difference (though it would have been very messy and unintuitive). A script can use whatever script messages it pleases, though there will also need to be a script listening for that message (it can be the same script) for it to be useful.

The ControlDevice link flavour also has no special meaning in the engine, other than that it is the standard method for a triggering script (like a button) to send messages to other objects. The System Shock 2 version of Dark uses the flavor SwitchLink instead of ControlDevice, and it makes no difference (except to confuse Thief Dromeders and to make script writers’ jobs more difficult). However, while you can use any name you please as script messages, you can’t add new link flavors to Dark – you are limited to the ones that are hard-coded into Dromed.

With a fair number of my scripts (the NVTrap and NVTrigger scripts), I have allowed you to choose which messages they should listen for and send, and where to send them to, via Editor→Design Note parameters. While most of them default to the standard TurnOn and TurnOff via ControlDevice system, you can use whatever messages or destinations you like. And example of this would be to have my NVOnscreenText script set up to trigger when the player frobs its object, by setting it to listen for FrobWorldEnd (for this script, this would be done by adding NVOnscreenTextOn="FrobWorldEnd" to its Editor→Design Note property). Another example might be to have my NVTrigQVar script send a Toggle message to objects down Owns links instead of TurnOn down ControlDevices links (in this case, NVTrigQVarTOn="Toggle"; NVTrigQVarTDest="&Owns").

The concept of design note parameters could probably use some explanation. Since it is obviously useful for the mission designer to be able to control the scripts on an object, rather than the scriptwriter having to rewrite them for every situation, the scripts need some Dromed property which the designer can use to configure them. Most of the properties in Dark already have a purpose, but the Editor→Design Note doesn’t really have one, plus it’s a very long field that can store a lot of text (a couple thousand of bytes). As such, it is an ideal place for scripts to store their extra configuration settings. Settings are written as parameters separated by semicolons, in the following format:


Where ParameterName is the name of the parameter that the script uses (and is dependent on each script), and Value is the value that the designer wants to set the parameter to. There does not need to be a semicolon after the last parameter. It is important to note that strings (text values) must be enclosed in double-quotes, like this:

  TextParameter="Some text"

Numerical values should not include these quotes:


Many of the messages that are sent to objects by the game engine have extra information associated with them. For example, the FrobWorldEnd message gives the object id of the frobber, the Alertness message gives the level of alertness that the AI has reached and the previous level of alertness the AI had before, and so on. Scripts can use this information if they wish.

Technically, the object must have Script set in the World Action section of its Engine Features→Frob Info property for this message to be sent. Also, if the player holds down the Frob button on the object, the message is only sent when the button is released. The game also sends FrobWorldBegin when the player first begins frobbing the object.
dromed/an_introduction_to_custom_scripts.txt · Last modified: 2010/11/23 23:16 by telliamed