Tags:
°SS2 °tutorial
An Introduction to ScriptsA 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 misssion .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 world*.
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 SwitchLink 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
SwitchLink 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 Thief version of Dark uses the flavour
ControlDevice instead of
SwitchLink, and it makes no difference. However, while you can use any name you please as script messages, you can’t add new link flavours 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 Objlist Args parameters. While most of them default to the standard ‘TurnOn/TurnOff via
SwitchLink’ system, you can use whatever messages or destinations you like. An 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 Objlist Args property). Another example might be to have my NVTrigQVar script send a Toggle message to objects down Owns links instead of TurnOn down
SwitchLink links (in this case,
NVTrigQVarTOn="Toggle"; NVTrigQVarTDest="&Owns").
The concept of objlist args parameters could probably use some explanation.
(You will also find these referred to as "Design Note parameters", as that is the property used in the Thief version of DromEd.)
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 Script->Objlist Args doesn’t really have one, plus it’s a very long field that can store a lot of text (was it 65536 characters?). 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:
ParameterName1=Value2;
Where ParameterName is the name of the parameter that the script uses (and is dependant 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:
NumericalParameter=5
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.)