Button Functionality and Frob Triggers
Originally written by Ishtvan on http://forums.thedarkmod.com/topic/4022
I added some global frob action scripts and button defs to make buttons more intuitive for the mapper.
Note: This doc relies on other information in the door documentation.
To create a simple button that triggers one or more entities when depressed
Place a func_darkmod_button in your map
Assign a brush or model for it as you would for a func_darkmod_door. Modify the translation direction and speed so that the button moves in the direction you want. (Again see the documentation for translation in doors, or see the "entity usage" tab in the editor).
Assign targets to the button
They will now be triggered when the button is depressed. For example, if you assign a light, the light will be turned on and off by the button.
To add a custom script to the button
If you want your button to do more than just trigger something, you'll need to write a script. There's two ways to go about this:
Entity Scriptobject Method (7 steps)
- Create your button as described above.
- Place a new entity of class: target_callobjectfunction
- Set the target of the target_callobjectfunction to itself (alternatively you could set it to another entity and call the script on that entity, but that's not necessary)
- Set the key "call" to the name of the script you will write
- Set the key "scriptobject" to the name of the script object you will define
- Go into the map's script file and create a new object, using the following code:
- Define a member function of this object with the script that you want to run, and write the script.
The code below describes generally how to do steps 6 and 7:
Code in <your map name>.script
object <object name> { // your script function declaration } <object name>::<your script function name> { // your script function implementation }
Global scope method (4 steps - probably easier)
- Create your button as described above.
- Set the key "state_change_callback" to the name of a script you'll define globally in the script file for your map. (Must be named <map name>.script).
- Unfortunately, due to how D3 scripting works, you'll have to copy the code to pop the button back up if you use the global scope method. Also, this script must have certain arguments because that's how it's called from the SDK. Copy and paste the following script for your button, replacing it with the name:
void <your function name>(entity button, boolean bOpen, boolean bLocked, boolean bInterrupted) { if(bOpen) { button.Close(1); } }
- Now, insert the script code that you want to run when the button is pressed here:
void state_change_button(entity button, boolean bOpen, boolean bLocked, boolean bInterrupted) { if(bOpen) { // YOUR CODE GOES HERE button.Close(1); } }
Example
Optionally, you could add some interesting behavior here, like the button stays down for a while and then calls another script when it pops back up. To do that, you could do this:
void state_change_secret_door(entity button, boolean bOpen, boolean bLocked, boolean bInterrupted) { if(bOpen) { // open the secret door for 30 seconds $secret_door_1.ToggleOpen(); sys.wait( 30 ); // close the secret door after 30 seconds $secret_door_1.ToggleOpen(); // pop the button back up button.Close(1); } }
Comparison of Methods A and B
In Method A, you did not have to copy & paste the code to pop the button back up, because you were not creating a new state change function, the state change happens as usual and then triggers the target_callobjectfunction to call the script. This is probably the only advantage of Method A, other than being more OO to have local script functions instead of map-global ones.
In Method B you do have to copy the code to pop the button back up, but it's probably easier in terms of the number of steps required, since you can just change one key on the button and then put a global-scope script in the map.script file.
Also: Added generic response of triggering of targets into the global frob action scripts (/scripts/tdm_frobactions.script).
To create an entity that only triggers another entity when frobbed, either place a "func_darkmod_frobable_base," or place any other item, set "frobable" to "1" and set "frob_action_script" to "frob_trigger"
Inventory items trigger their targets when frobbed, doors trigger their targets when frobbed. Note that in these cases, the trigger is sent on every frob. That means if a player spasmadically presses frob 30 times in a second, the trigger will be sent 30 times, so you'd better make sure it is a target is a trigger_once or something like that if you don't want your trigger executing 30 times. Also if an item is trapped when you pick it up, make sure the trap can only get triggered once and then stops receiving triggers, otherwise it will keep going off if you drop the item and pick it up again and again.
If you want more complicated behavior for doors to trigger their targets only when completely open or closed, you'll have to either write your own state_change_callback script or use Sparhawk's setup for frobables triggering other frobables that should be covered in the door documentation.