UNPKG

isaacscript-common

Version:

Helper functions and features for IsaacScript mods.

244 lines (216 loc) • 7.75 kB
import { ButtonAction, Controller, ControllerIndex, Keyboard, } from "isaac-typescript-definitions"; import { CONTROLLER_INDEX_VALUES } from "../cachedEnumValues"; import { KEYBOARD_TO_STRING_MAP } from "../maps/keyboardToStringMap"; import { ReadonlySet } from "../types/ReadonlySet"; import { trimPrefix } from "./string"; export const MODIFIER_KEYS = [ Keyboard.LEFT_SHIFT, // 340 Keyboard.LEFT_CONTROL, // 341 Keyboard.LEFT_ALT, // 342 Keyboard.LEFT_SUPER, // 343 Keyboard.RIGHT_SHIFT, // 344 Keyboard.RIGHT_CONTROL, // 345 Keyboard.RIGHT_ALT, // 346 Keyboard.RIGHT_SUPER, // 347 ] as const; export const MOVEMENT_BUTTON_ACTIONS = [ ButtonAction.LEFT, // 0 ButtonAction.RIGHT, // 1 ButtonAction.UP, // 2 ButtonAction.DOWN, // 3 ] as const; export const MOVEMENT_BUTTON_ACTIONS_SET = new ReadonlySet<ButtonAction>( MOVEMENT_BUTTON_ACTIONS, ); export const SHOOTING_BUTTON_ACTIONS = [ ButtonAction.SHOOT_LEFT, // 4 ButtonAction.SHOOT_RIGHT, // 5 ButtonAction.SHOOT_UP, // 6 ButtonAction.SHOOT_DOWN, // 7 ] as const; export const SHOOTING_BUTTON_ACTIONS_SET = new ReadonlySet<ButtonAction>( SHOOTING_BUTTON_ACTIONS, ); /** * Helper function to get the enum name for the specified `Controller` value. Note that this will * trim off the "BUTTON_" prefix. * * Returns undefined if the submitted controller value was not valid. */ export function controllerToString(controller: Controller): string | undefined { const key = Controller[controller]; // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (key === undefined) { return undefined; } return trimPrefix(key, "BUTTON_"); } /** * Helper function to get the movement actions that the specified `ControllerIndex` is currently * pressing down. This returns an array because a player can be holding down more than one movement * key at a time. */ export function getMoveButtonActions( controllerIndex: ControllerIndex, ): readonly ButtonAction[] { return MOVEMENT_BUTTON_ACTIONS.filter((buttonAction) => Input.IsActionPressed(buttonAction, controllerIndex), ); } /** * Helper function to get the shooting actions that the specified `ControllerIndex` is currently * pressing down. This returns an array because a player can be holding down more than one shooting * key at a time. */ export function getShootButtonActions( controllerIndex: ControllerIndex, ): readonly ButtonAction[] { return SHOOTING_BUTTON_ACTIONS.filter((buttonAction) => Input.IsActionPressed(buttonAction, controllerIndex), ); } /** * Helper function to check if a player is pressing a specific button (i.e. holding it down). * * This is a variadic version of `Input.IsActionPressed`, meaning that you can pass as many buttons * as you want to check for. This function will return true if any of the buttons are pressed. */ export function isActionPressed( controllerIndex: ControllerIndex, ...buttonActions: readonly ButtonAction[] ): boolean { return buttonActions.some((buttonAction) => Input.IsActionPressed(buttonAction, controllerIndex), ); } /** * Helper function to iterate over all inputs to determine if a specific button is pressed (i.e. * being held down). * * This function is variadic, meaning you can pass as many buttons as you want to check for. This * function will return true if any of the buttons are pressed. */ export function isActionPressedOnAnyInput( ...buttonActions: readonly ButtonAction[] ): boolean { return CONTROLLER_INDEX_VALUES.some((controllerIndex) => isActionPressed(controllerIndex, ...buttonActions), ); } /** * Helper function to check if a player is triggering a specific button (i.e. pressing and releasing * it). * * This is a variadic version of `Input.IsActionTriggered`, meaning that you can pass as many * buttons as you want to check for. This function will return true if any of the buttons are * triggered. */ export function isActionTriggered( controllerIndex: ControllerIndex, ...buttonActions: readonly ButtonAction[] ): boolean { return buttonActions.some((buttonAction) => Input.IsActionTriggered(buttonAction, controllerIndex), ); } /** * Iterates over all inputs to determine if a specific button is triggered (i.e. held down and then * released). * * This function is variadic, meaning you can pass as many buttons as you want to check for. This * function will return true if any of the buttons are pressed. */ export function isActionTriggeredOnAnyInput( ...buttonActions: readonly ButtonAction[] ): boolean { return CONTROLLER_INDEX_VALUES.some((controllerIndex) => isActionTriggered(controllerIndex, ...buttonActions), ); } /** * Helper function to see if a specific keyboard key is being held down by the player. * * This function is variadic, meaning you can pass as many keyboard values as you want to check for. * This function will return true if any of the values are pressed. */ export function isKeyboardPressed(...keys: readonly Keyboard[]): boolean { return keys.some((key) => Input.IsButtonPressed(key, ControllerIndex.KEYBOARD), ); } /** * Helper function to check if one or more modifier keys are being pressed down on the keyboard. * * A modifier key is defined as shift, control, alt, or Windows. */ export function isModifierKeyPressed(): boolean { return isKeyboardPressed(...MODIFIER_KEYS); } export function isMoveAction(buttonAction: ButtonAction): boolean { return MOVEMENT_BUTTON_ACTIONS_SET.has(buttonAction); } export function isMoveActionPressed(controllerIndex: ControllerIndex): boolean { return isActionPressed(controllerIndex, ...MOVEMENT_BUTTON_ACTIONS); } export function isMoveActionPressedOnAnyInput(): boolean { return MOVEMENT_BUTTON_ACTIONS.some((moveAction) => isActionPressedOnAnyInput(moveAction), ); } export function isMoveActionTriggered( controllerIndex: ControllerIndex, ): boolean { return isActionTriggered(controllerIndex, ...MOVEMENT_BUTTON_ACTIONS); } export function isMoveActionTriggeredOnAnyInput(): boolean { return MOVEMENT_BUTTON_ACTIONS.some((moveAction) => isActionTriggeredOnAnyInput(moveAction), ); } export function isShootAction(buttonAction: ButtonAction): boolean { return SHOOTING_BUTTON_ACTIONS_SET.has(buttonAction); } export function isShootActionPressed( controllerIndex: ControllerIndex, ): boolean { return isActionPressed(controllerIndex, ...SHOOTING_BUTTON_ACTIONS); } export function isShootActionPressedOnAnyInput(): boolean { return SHOOTING_BUTTON_ACTIONS.some((shootAction) => isActionPressedOnAnyInput(shootAction), ); } export function isShootActionTriggered( controllerIndex: ControllerIndex, ): boolean { return isActionTriggered(controllerIndex, ...SHOOTING_BUTTON_ACTIONS); } export function isShootActionTriggeredOnAnyInput(): boolean { return SHOOTING_BUTTON_ACTIONS.some((shootAction) => isActionTriggeredOnAnyInput(shootAction), ); } /** * Helper function to get the string that would be typed if someone pressed the corresponding key. * This is useful for creating in-game chat. * * Note that this function will only work for the keyboard values that are printable. Thus, it will * return undefined for e.g. `Keyboard.LEFT_SHIFT` (340). If all you want is the corresponding name * of the key, then simply use the enum reverse mapping (e.g. `Keyboard[keyboard]`). */ export function keyboardToString( keyboard: Keyboard, uppercase: boolean, ): string | undefined { const tuple = KEYBOARD_TO_STRING_MAP.get(keyboard); if (tuple === undefined) { return undefined; } const [lowercaseCharacter, uppercaseCharacter] = tuple; return uppercase ? uppercaseCharacter : lowercaseCharacter; }