A to Z Scripting: Ways of calling a script
TDM has many methods for calling scripts. Often you can combine systems such as the objective system with scripting in order to get powerful results that wouldn't easily be possible otherwise. Some methods overlap, but there are subtle differences that justify each method in specific situations. For example a frob_action_script can be applied with a single spawnarg, while a frob response can be deactivated.
From other scripts
The main advantage of calling one script from another is that you can give as much input as you like - if the called script is designed to use input (see A to Z Scripting: Scripts that use input variables for more). Entity-based methods can usually only provide 1 or 2 pieces of input: the entity that called the script (i.e. a trigger brush) and the entity that triggered the calling entity (i.e. a player or AI stepping into the trigger brush).
To call a script from another script, simply write the name of the script followed by input brackets. The script will wait for the called script to finish.
void script2() { script1(); //call script1, wait for script1 to finish }
Alternatively, you can write "thread" in front. Both scripts will run simultaneously, because each one runs in its own thread.
void script2() { thread script1(); //call script1 }
You can only call scripts that the engine already knows about, so the called script (script1) needs to be higher up than the calling script (script2). If you're using general .script files (A to Z Scripting: Setting up the .script files), the same applies to the order in which you #include your .script files.
If the script you're calling needs input parameters, you always need to include some in the call. Example:
void move_mover(entity name_of_mover, vector move_destination) { name_of_mover.speed(20); name_of_mover.moveToPos(move_destination); } void move_box1() { thread move_mover($box1, '100 0 0'); //tell move_mover() to move box1 to '100 0 0' }
Trigger brushes
Trigger brushes are a common way to call scripts, activated when the player or an AI enters the volume of the brush. Like with target_callscriptfunction entities, they need a "call" spawnarg naming the script to be called. See Triggers for details on their creation and the various types.
If you want your script to know which entity has activated the trigger brush, you can give your script an entity as an input parameter.
Example:
void script1(entity activator) { sys.println(activator.getName() + " has stepped into the trigger brush."); }
- Potential pitfall: AIs will stop activating trigger_multiple brushes if they become stationary.
- Potential pitfall: trigger_touch brushes can be resource-intensive if continuously active. It's recommended to activate them only for a single frame, then switch them off again.
target_callscriptfunction
You can create an entity in DR called target_callscriptfunction and give it the spawnarg "call" with the name of the script without brackets. Whenever this entity is triggered, i.e. by a button or if an AI reaches a path_node that targets this, the script will be called. As far as I'm aware, it's not possible to pass any input parameters when calling a script this way.
Example:
The script in the .script file:
void script1() { ... }
The spawnarg on the target_callscriptfunction entity in DR:
"call" "script1"
Path nodes
Many Path Nodes trigger all of their non-path-node targets whenever an AI reaches them. They can target a target_callscriptfunction entity in order to call a script.
Stim/Response
The Stim/Response system is very versatile, in particular when augmented with scripting.
In most cases, you'll likely be interested in only the "Response" tab of the S/R editor interface. This allows you to make an entity respond to certain stimuli, such as a frob, a trigger or water by executing various effects, such as running a script. Many other effects are available from the dropdown list.
One common use is to make an entity frobable and give it a "Response" to frobbing with an effect to run a script. To do so, set the spawnarg "frobable" "1" on the entity to make it frobable. Then open the S/R editor, go to the Response tab, in the left half of the window add a "Frob" entry, in the right half of the window right-click and add an effect to "Run script", naming the script you want to run.
To make this single-use you could add another effect to either:
- disable frobability of this entity
- or deactivate the response to frobbing (the ID of the frob stim is 0).
Action scripts
Entities can be given spawnargs that make them run scripts when certain actions are performed on them, such as frobbing or using. The value of the spawnarg is the name of the script. Example: "frob_action_script" "script1".
Like with trigger brushes (see earlier), these entities pass their own name to the script function. This allows you to reuse the same spawnarg & script on many entities.
frob_action_script | Calls the specified script when the entity is frobbed by the player. |
use_action_script | Calls the specified script when the player uses an inventory item on the entity (i.e. uses a key on a door). The inventory item must be named in a "used_by" spawnarg on the entity. More info here: Tool, Key, custom used by inventory actions |
equip_action_script | Calls the specified script when the player is holding the entity and uses it (i.e. eating a held apple by pressing enter). |
Signals
Signals are events which can be setup to call a script. Examples of events are the entity being triggered, frobbed, removed or damaged. Some signals only work for movers i.e. when a mover is blocked or a door is closed/opened. See the Signals wiki article for a full list of available signals.
Note that the signal system is old, so the signal for frobbing is called SIG_TOUCH. The SIG_USE signal refers to a player holding an object and pressing the 'use' key (default enter), as far as I'm aware.
To use the signal system, you need to use a script event to instruct the entity to respond to a certain signal by running a certain script. Example:
sys.onSignal(SIG_TRIGGER, $func_static_1, "script1");
You may later want to disable this again. In that case:
sys.clearSignalThread(SIG_TRIGGER, $func_static_1);
Objective system
The Objectives Editor can be seen as a visual scripting editor. Not unsurprisingly it synergises well with scripting.
The main way to use the objective system for scripting is by specifying completion scripts and failure scripts for when an objective is completed or failed. Note that if the objective is reversible, it might call the scripts multiple times.
The objectives system allows you to do some things much more easily than with regular scripting, such as calling a script when reaching a certain page in a book (i.e. playing an ominous sound). Many maps use a mix of hidden objectives and scripts in order to achieve interesting scripted effects.
Location system
The location system (wiki page: Location Settings allows you to call scripts whenever the player enters or leaves specific locations.
It works by setting spawnargs on the info_location entity, with the value being the script's name:
"call_on_entry" "call_on_exit" "call_once_on_entry" "call_once_on_exit"
On the scripting side of things, your script must specify the location where it's called in its input brackets. Note that this is without a $ sign. Example:
void enter_location_streets(entity info_location_streets) //for an info_location entity with the name "info_location_streets"
To my knowledge, this way of setting up means a script can only be called from one location. If you have multiple locations, you will need multiple scripts even if they do the same thing.
From the console
This is only for testing purposes because you will no longer be able to save the game after calling a script from the console. The command is the same as when calling a script from another script, i.e. thread name_of_script();
Next / previous article
- Next article: A to Z Scripting: Getting map information
- Previous article: A to Z Scripting: Setting up the .script files
- Table of contents: A to Z Scripting