====== Input library ====== ACSUtils provides a set of wrappers for [[zdoom>GetPlayerInput]] to make writing correct input code easier. ===== Basic concepts ===== * Every key is either **up** or **down** at any time. * If the key was up the previous tic, but is now down, it is said to have been **pressed**. * If the key was down the previous tic, but is now up, it is said to have been **released**. * If the key has been pressed or released, it is said to have been **toggled**. ACSUtils provide a way to easily check these all these states for every key without writing compliated ''GetPlayerInput'' expressions. ===== What's the point of "pressed" and "released"? ===== Say, you have an on-screen button to sell items that can be [[mouse|clicked with mouse]]: if (/* check that mouse cursor is inside the button */) if (GetPlayerInput(-1, INPUT_BUTTONS) & BT_ATTACK)) // check left mouse button click SellItem(); **This code is wrong.** If the player clicks the button once, it will likely cause him to sell multiple items. That's because this code checks if the mouse button is **down**. But the mouse button may be down for multiple tics after a click, as it may not be immediately released. To avoid this bug, you need to check if the button was up the previous tic, but is now down. And that's exactly what the **pressed** state means. The ''KeyPressed'' function contains all the repetitive code to perform this check: if (/* check that mouse cursor is inside the button */) if (KeyPressed(BT_ATTACK)) // check left mouse button click SellItem(); Now the button works correctly. Performing an action on releasing the button can be done the same way using ''KeyReleased''. ===== Functions ===== To check one key or a key combination: * ''bool KeyUp(int key)'' * ''bool KeyDown(int key)'' * ''bool KeyPressed(int key)'' * ''bool KeyReleased(int key)'' * ''bool KeyToggled(int key)'' Examples: Checking one key: if (KeyPressed(BT_ATTACK)) print(s:"You clicked left mouse button"); Checking a key combination: if (KeyDown(BT_FORWARD | BT_BACK)) print(s:"You are trying to move forward and back at the same time." s:"You are not going anywhere this way."); If you try to use ''KeyPressed'' with a key combination, you are requiring that the whole combination is pressed within the same tic. It is extremely hard to do so. To check if at least one of the keys is in a given state: * ''bool KeyUpAny(int keys)'' * ''bool KeyDownAny(int keys)'' * ''bool KeyPressedAny(int keys)'' * ''bool KeyReleasedAny(int keys)'' * ''bool KeyToggledAny(int keys)'' For example: if (KeyPressedAny(BT_ATTACK | BT_ALTATTACK)) print(s:"You just tried to shoot."); if (KeyDownAny(BT_FORWARD | BT_BACK | BT_MOVELEFT | BT_MOVERIGHT)) print(s:"You are trying to move."); To use these wrappers on players other than the activator, prefix any of the above functions with ''Player'' and add player number as the first argument: * ''bool PlayerKeyUp(int player, int key)'' * ''bool PlayerKeyDown(int player, int key)'' * ''bool PlayerKeyPressed(int player, int key)'' * ''bool PlayerKeyReleased(int player, int key)'' * ''bool PlayerKeyToggled(int player, int key)'' * ''bool PlayerKeyUpAny(int player, int keys)'' * ''bool PlayerKeyDownAny(int player, int keys)'' * ''bool PlayerKeyPressedAny(int player, int keys)'' * ''bool PlayerKeyReleasedAny(int player, int keys)'' * ''bool PlayerKeyToggledAny(int player, int keys)''