This article describes how the stim/response system works for The Dark Mod. The name is taken from the Dromed Stim/Response system. However this does not mean that you should assume any other similarities. The system was described to me (sparhawk) and I coded it accordingly, but I have no Dromed experience, beyond some very simple maps, without any special features. I never got beyond the "Create a room and texture it" stage. :) So while this system may be similar on how it works as seen by the users, you can't assume that this is is more then a fleeting similarity as defined by it's common requirements.
How does it work?
The general concept is pretty easy to understand. The mapper populates his map with entities. Each of these entities can be either a kind of actor (a stim) or an actee (the response). Any entity can be both at the same time, however stims don't affect the owner itself. So if the entity carries a stim and it triggers, it will not act on himself, even if the entity has a response for that stim. Stims and responses are defined by numbers. The Dark Mod already defines some very common stims (like water) and reserves numbers for them. For a complete list you should take a look at tdm_stim_response.script in the script folder. You will notice that there is one stim named USER. This stim has no special meaning. Instead it defines the lowest number that users can use for themselves. So if you define new stims to be used in your maps, you should use USER+N for your individual stims. All numbers below USER are assumed to be known stims and may trigger specific actions if needed, which possibly includes specific SDK support code.
As explained above, stims and responses are identified by their id's (the numbers). Whenever a stim is active, the system evaluates all stims and checks if appropriate responses are within its reach. A response is identified by having the same id as the stim. When such a response is found, the response is triggered and a script action is executed for it. If the response doesn't have a script action associated, nothing will happen, but this is usually a waste of CPU, unless the response is coded in C++ directly in the SDK. One major difference between stims and responses is that responses have an action associated with them, while stims don't.
Stims and responses can be enabled and disabled at runtime. This is not only a feature, it is very important for the health of the system. If stims are not destroyed after they are used up, they will take up memory and hog your machine down over time. Also accumulating stims will cause the system to respond slower over time as more and more stims have to be tested. For example: The arrows (like the water arrow) will spawn an entity that carries the water stim when the arrow explodes. If that stim is not destroyed, it will continue to fire. Once a water arrow is exploded it doesn't makes sense though to keep it running, so it has to be destroyed. However, there is no definite rule when a stim has to be destroyed because it depends on its actual usage. Some stims may run throughout the game and others should be destroyed after they are used up.
How to set it up?
Bascially there are several methods to create a stim/response. The most obvious one is to add it in the SDK code, but this is probably the least preferred. For all practical purposes, stims and responses should be added either via scripting or the map editor, without the need of coding in the SDK environment.
Configuring Stims/Responses in DarkRadiant
Since release 0.9.0 DarkRadiant is capable of setting up stims and responses via a graphical interface. To open the Stim/Response Editor, select your entity and choose the command from the menu:
The Stim/Response Editor will pop up and allow you to define stims and responses for your entity. I'll go briefly over the properties of stims and responses in the following sections.
A Stim is the equivalent to DromEd's Source and can be of various types (Frob, Heal, Damage, Trigger, Sound, Visual, Communication, whatever). Each stim can be either active or inactive, which can be controlled via ticking the checkbox "Active" accordingly.
Most stims need to have a radius defined, that specifies their action area. The radius is measured in Doom Units and its value depends on the purpose of your stim. A torchflame for example has a Fire Stim with a radius of 10, which is fairly small (~25 cm, ~10 inches). One can also set up a stim whose radius is growing during the stim's lifetime, by setting radius_final (this requires a non-zero duration being set on the stim).
The second important parameter is the magnitude of the stim. For instance, the fire stim of a torch is supposed to have a smaller magnitude than a lava stream.
The magnitude can be either constant over the whole stim range or follow a certain falloff function as defined by the falloff exponent. A falloffexponent of 0 means that the magnitude is constant over the whole range, which is the default:
- 0 = no falloff (magnitude is constantly at maximum value over the whole radius)
- 1 = linear falloff
- 2 = quadratic falloff
- 3 = etc.
The higher the number, the faster the magnitude is decreasing with the distance. The magnitude is reaching zero as soon as the distance of the responding object is greater than or equal to the stim radius, except for falloffexponent = 0 (no falloff). Negative values are allowed as well, making it possible to actually increase the magnitude of a stim with larger distance < radius. Don't know if that makes sense, though, and I haven't tested it either.
Stim/Response Key/Value Definitions
These can be found here: Stim/Response Key/Values (with examples also)