GetPlayerInput
int GetPlayerInput (int player, int input)
Usage
Returns information regarding the keyboard, mouse and joystick input of the specified player at this exact moment or the previous game tic. This can be used to create effects such as key pads or on-screen mouse cursors in your maps, or simply to act on player input directly instead of relying on other methods of determining the player's actions.
Note that this function does not read the player's input devices directly. Instead, it will only report information about which binds the player is using. For example, you cannot check to see if the player is pressing “W”, but you can check to see if they are using +forward. This design is intended to prevent abuse, as well as making the function more adaptable (since here the player can freely rebind +forward and still have the script work for them).
Parameters
- player
- The number of the player you want to get information on. Player 1 is 0, player 2 is 1, etc. Use -1 to specify the script activator instead.
- input
- The player input you wish to check. To use, specify one of the following flags. All flags come in two varieties; The INPUT_* series checks the player's raw input, e.g. the keys they are actually pressing. The MODINPUT_* series check the values after they have been processed by the game engine. These may be different if, for example, the player is fully or partially frozen (Movement inputs will be nulled) or is using a weapon such as the chainsaw which alters the player's input to include forward movement.
- INPUT_BUTTONS
- MODINPUT_BUTTONS
- The movement commands that are currently active. See the table below for instructions on how to read individual controls.
- In ZScript it corresponds to the
buttons
field of the UserCmd struct.
- INPUT_OLDBUTTONS
- MODINPUT_OLDBUTTONS
- The movement commands that were active during the previous tic. By comparing this value with INPUT_BUTTONS, you can determine the exact moment when the player presses or releases a key.
- In ZScript it corresponds to the
oldbuttons
field of the PlayerInfo struct.
- INPUT_PITCH
- MODINPUT_PITCH
- The pitch movement of the player. Looking up returns positive values, down returns negative. Maximum value is 32767.
- In ZScript it corresponds to the
pitch
field of the UserCmd struct.
- INPUT_YAW
- MODINPUT_YAW
- The yaw motion of the player. Turning left returns positive values, right returns negative. Maximum value is 32767.
- In ZScript it corresponds to the
yaw
field of the UserCmd struct.
- INPUT_ROLL
- MODINPUT_ROLL
- In ZScript it corresponds to the
roll
field of the UserCmd struct. - Not currently used.
- INPUT_FORWARDMOVE
- MODINPUT_FORWARDMOVE
- The forward/backward movement of the player. Forward is positive, reverse is negative. Maximum positive value is 12800, save with negative except negative; walking speed is half that (6400). This is useful to compare to if the intent is to see if the player is walking or running and at specific player-intended speeds if a joystick axis is used.
- In ZScript it corresponds to the
forwardmove
field of the UserCmd struct.
- INPUT_SIDEMOVE
- MODINPUT_SIDEMOVE
- The side-to-side (strafing) movement of the player. Left is negative, right is positive. Maximum positive value is 10240. When walking, this becomes 6144.
- In ZScript it corresponds to the
sidemove
field of the UserCmd struct.
- INPUT_UPMOVE
- MODINPUT_UPMOVE
- The up or down movement of the player (flying or swimming). Upwards is positive, down is negative.
- In ZScript it corresponds to the
upmove
field of the UserCmd struct.
- Note that these only return the input being received by ZDoom from the specified player, and do not correlate to the actual movement (if any) of the player. In other words, INPUT_SIDEMOVE may be used to measure the amount of force a player is putting on an analog axis (such as a joystick or mouse) bound to the strafe inputs. Therefore, if the player is stuck in a small room and cannot move any further in the specified direction, this function will still return the value that the player is trying to make the player move, not the actual player's end movement.
Return value
If input is one of the *BUTTONS flags, the return value is a bitmask representing the inputs that the specified player is currently using from the given category. Otherwise, the return value is a scalar value representing the amount of input being applied to the specified control. If the specified player is not in the game, the return value is always 0.
Reading buttons
Note: Currently, joystick or mouse axes bound to movement will not set the corresponding button for the purposes of reading by this function. (E.g. moving forward by pressing forward on an analog joystick will not set the BT_FORWARD key.) However, pressing a keyboard key does set the axis inputs. Therefore, it is recommended that mod authors read the axes above whenever possible, instead of relying on [MOD]INPUT_[OLD]BUTTONS to read directional movement. |
To properly use GetPlayerInput for button presses, you will need to check the result value against a set of defined controls to determine which ones the player is using. You can do this by using the bitwise AND operator (&) in your code, as in this example:
int buttons = GetPlayerInput(-1, INPUT_BUTTONS); if (buttons & BT_FORWARD) { print(s:"You are pressing the move forward key."); }
The bitwise OR operator (|) can be used to check for multiple buttons.
int buttons = GetPlayerInput(-1, INPUT_BUTTONS); if (buttons & (BT_USE|BT_ATTACK)) { print(s:"You could be pressing the use key, or the attack key."); }
The following buttons can be read in ACS:
Internal name in ZScript or ACS | Corresponding action |
---|---|
BT_FORWARD | Walk forward |
BT_BACK | Walk backward |
BT_LEFT | Turn left |
BT_RIGHT | Turn right |
BT_MOVELEFT | Strafe left |
BT_MOVERIGHT | Strafe right |
BT_ATTACK | Fire primary |
BT_ALTATTACK | Fire secondary |
BT_USE | Use/Open |
BT_JUMP | Jump |
BT_CROUCH | Crouch |
BT_TURN180 | 180-degree turn |
BT_RELOAD | Reload weapon |
BT_ZOOM | Zoom weapon |
BT_SPEED | Run/walk modifier |
BT_RUN | Run/walk state |
BT_STRAFE | Strafe modifier |
BT_LOOKUP | Look up (Keyboard) |
BT_LOOKDOWN | Look down (Keyboard) |
BT_MOVEUP | Swim/fly upward |
BT_MOVEDOWN | Swim/fly downward |
BT_SHOWSCORES | Show multiplayer scoreboard |
BT_USER1 | User-defined button 1 |
BT_USER2 | User-defined button 2 |
BT_USER3 | User-defined button 3 |
BT_USER4 | User-defined button 4 |
The four user-defined buttons (+user1, -user1, +user2, -user2 etc) can now be used for weapons, and have been included for usage with this function so that mod authors can implement up to four custom inputs which the player can bind in the controls menu.
BT_RUN and BT_SPEED
BT_RUN reflects the running/walking state, not merely whether the speed button is pressed or not like the case with BT_SPEED. This distinction becomes evident when autorun is involved.
Action | State | BT_SPEED | BT_RUN |
---|---|---|---|
Speed button not pressed; autorun disabled | Walking | Not set | Not set |
Speed button pressed; autorun disabled | Running | Set | Set |
Speed button not pressed; autorun enabled | Running | Not set | Set |
Speed button pressed; autorun enabled | Walking | Set | Not set |
Examples
This simple example prints a message if the player presses both the forward and back buttons at the same time, thereby canceling his forward or backward movement.
script 1 ENTER { int buttons; while (TRUE) { buttons = GetPlayerInput(-1, INPUT_BUTTONS); if (buttons & BT_FORWARD && buttons & BT_BACK) { print(s:"Are you coming or going?"); } delay(1); } }
This example demonstrates how to make a simple three digit combination lock. In this case, there are three locks. The lock combination that is used is specified by passing a value between 0 (the first) and 2 (the third) in the first argument. When adding or subtracting locks, be sure to define the NUM_LOCKS constant and lock_code array accordingly. Also, be sure to adjust the number of cases in the switch statement at the end of the script as well.
#define NUM_LOCKS 3 int lock_code[NUM_LOCKS][3] = {{6, 9, 1}, {3, 2, 5}, {1, 7, 3}}; int digit_pick[3]; bool lock_picked[NUM_LOCKS]; script 1 (int this_lock) { if (!lock_picked[this_lock]) { int buttons, count, match, quit, wait; SetHudSize(640, 480, 1); HudMessage(s:"Forward and back change digits, use to pick, and fire to exit."; HUDMSG_PLAIN, 1, CR_WHITE, 0.1, 30.1, 0.0); SetPlayerProperty(0, ON, PROP_TOTALLYFROZEN); while (count < 3 && !quit) { buttons = GetPlayerInput(-1, INPUT_BUTTONS); if (buttons & BT_ATTACK) { quit = 1; } else if (buttons & BT_FORWARD) { digit_pick[count]++; digit_pick[count] %= 10; } else if (buttons & BT_BACK) { digit_pick[count] += 9; digit_pick[count] %= 10; } else if (buttons & BT_USE) { count++; } if (count < 3) { HudMessage(i:digit_pick[count]; HUDMSG_PLAIN, 2+count, CR_RED, 305.0+count*10.0, 240.0, 0); do { delay(1); wait++; } while (GetPlayerInput(-1, INPUT_BUTTONS) == buttons && wait < 5); wait = 0; } } if (!quit) { for (int i=0; i<3; i++) { if (lock_code[this_lock][i] == digit_pick[i]) { match++; } digit_pick[i] = 0; } if (match == 3) { HudMessage(s:"Lock combination accepted."; HUDMSG_FADEOUT, 5, CR_GREEN, 320.0, 200.0, 3.0, 1.0); lock_picked[this_lock] = 1; switch (this_lock) { case 0: //action for lock 1 break; case 1: //action for lock 2 break; case 2: //action for lock 3 break; } } else { HudMessage(s:"Invalid lock combination."; HUDMSG_FADEOUT, 5, CR_RED, 320.0, 200.0, 3.0, 1.0); } } HudMessage(s:""; 0, 1, 0, 0, 0, 0); HudMessage(s:""; 0, 2, 0, 0, 0, 0); HudMessage(s:""; 0, 3, 0, 0, 0, 0); HudMessage(s:""; 0, 4, 0, 0, 0, 0); SetPlayerProperty(0, OFF, PROP_TOTALLYFROZEN); } }
Important note
There have been recommendations to use '==' and '!=' to check for a single input bit being set. Please note that this advice is wrong and should not be followed! Always use '&' and '|' with the appropriate bits being checked.