3rd February 2012
Detecting Keypresses
Thanks to FOSE's IsKeyPressed function, it is possible to detect when a certain key is pressed, and run some code when it happens. This makes it possible to turn any key into a hotkey that activates a scripted action.
IsKeyPressed takes a single parameter, which specifies a key by its DirectX Scancode. It returns 1 when the specified key is being pressed, and 0 when it is not being pressed. Because of this, in order to run some code once when a key is pressed, it is necessary to store the previous state of the key in a variable.
Using the "N" key (scancode 49) as an example:
int bIsNPressed Begin GameMode if bIsNPressed != IsKeyPressed 49 ; N set bIsNPressed to IsKeyPressed 49 ; N endif End
Initially, the value of the variable "bIsNPressed" (which I have prefixed with "b" to specify that it is used to store boolean values only) is 0. "0 != IsKeyPressed 49" will return 1 when IsKeyPressed returns 1.
As soon as this happens, the value of "bIsNPressed" is set to the return value of IsKeyPressed, so the condition won't evaluate to 1 again until the value returned by IsKeyPressed changes to 0.
"bIsKeyPressed != IsKeyPressed 49" will always return 1 during the frame that the return value of IsKeyPressed changes. This will occur under two circumstances:
- The "N" key is pressed
- The "N" key is released
If "N" was just pressed, "bIsNPressed" will be 1. Likewise, if "N" was just released, "bIsNPressed" will be 0:
int bIsNPressed Begin GameMode if bIsNPressed != IsKeyPressed 49 ; N set bIsNPressed to IsKeyPressed 49 ; N if bIsNPressed ; N has been pressed else ; N has been released endif endif End
Sometimes, it can be useful to assign multiple functions to a hotkey. This can be done in a variety of ways, such as specifying a modifier key to be used, or giving the key a different function depending on whether it is held down or just tapped.
Multiple functions via a modifier:
int bIsNPressed Begin GameMode if bIsNPressed != IsKeyPressed 49 ; N set bIsNPressed to IsKeyPressed 49 ; N if bIsNPressed if IsKeyPressed 50 ; M ; Function 2 else ; Function 1 endif endif endif End
Because we only detect when the state of the scripted hotkey changes, the modifier key must be held down beforehand. In this example, holding "N" and tapping "M" will not activate the second function, but holding "M" and tapping "N" will.
Other modifiers, such as whether or not the player is currently sneaking, can be used just as easily in the same way.
Multiple functions by holding or tapping:
int bIsNPressed int bNHeld float fTimer Begin GameMode if fTimer > 0 set fTimer to fTimer - GetSecondsPassed elseif bIsNPressed > bNHeld ; bIsNPressed == 1 && bNHeld == 0 set bNHeld to 1 ; Function 2 (Held) endif if bIsNPressed != IsKeyPressed 49 ; N set bIsNPressed to IsKeyPressed 49 ; N if bIsNPressed set fTimer to 0.8 set bNHeld to 0 elseif fTimer > 0 set fTimer to 0 ; Function 1 (Tapped) endif endif End
A similar script to this one can be used to assign a function which depends on how long the key was held for, which could be useful for something like an attack that gets powered up gradually:
int bIsNPressed int bNHeld float fTimer Begin GameMode if fTimer > 0 set fTimer to fTimer - GetSecondsPassed elseif bIsNPressed > bNHeld ; bIsNPressed == 1 && bNHeld == 0 set bNHeld to 1 ; Function 6 (Held 5 seconds) endif if bIsNPressed != IsKeyPressed 49 ; N set bIsNPressed to IsKeyPressed 49 ; N if bIsNPressed set fTimer to 5 set bNHeld to 0 else set fTimer to 0 if fTimer < 1 ; Function 5 (Held 4 seconds then released) elseif fTimer < 2 ; Function 4 (Held 3 seconds then released) elseif fTimer < 3 ; Function 3 (Held 2 seconds then released) elseif fTimer < 4 ; Function 2 (Held 1 second then released) elseif fTimer < 5 ; Function 1 (Tapped) endif endif endif End
If you're confused at all by my "bIsNPressed > bNHeld" expression, keep in mind that both of these variables will only ever take two values - 0 or 1. The only combination which satisfies that condition is when "bIsNPressed" is 1, and "bNHeld" is 0. I've used this method because it's more efficient than the commented expression.