diff --git a/code/components/extra-natives-five/src/InputNatives.cpp b/code/components/extra-natives-five/src/InputNatives.cpp index fbf8cb34eb..2e84978c34 100644 --- a/code/components/extra-natives-five/src/InputNatives.cpp +++ b/code/components/extra-natives-five/src/InputNatives.cpp @@ -4,6 +4,8 @@ #include #include +#include "nutsnbolts.h" + constexpr int KEYS_COUNT = 256; using keysData = unsigned char[2][KEYS_COUNT]; @@ -36,64 +38,81 @@ inline int ioKeyboard_KeyReleased(int key) return (*ioKeyboardKeys)[*ioKeyboardActive ^ 1][key] & ioKeyboard_KeyChanged(key); } -static HookFunction initFunction([]() -{ - ioKeyboardActive = hook::get_address(hook::get_pattern("8B 2D ? ? ? ? 48 8B 03"), 2, 6); - ioKeyboardKeys = hook::get_address(hook::get_pattern("48 8D 2D ? ? ? ? 49 C1 E6"), 3, 7); +// List of raw keys to count as disabled until the next frame +static std::set disabledKeys{}; - fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_PRESSED", [](fx::ScriptContext& context) +template +static bool IsRawKeyInvalidOrDisabled(int key) +{ + if constexpr (HandleDisabled) { - auto rawKeyIndex = context.GetArgument(0); - - if (rawKeyIndex >= 0 && rawKeyIndex < KEYS_COUNT) - { - context.SetResult(ioKeyboard_KeyPressed(rawKeyIndex) != 0); - } - else + if (disabledKeys.find(key) != disabledKeys.end()) { - context.SetResult(false); + // the key should be disabled + return true; } - }); + } - fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_RELEASED", [](fx::ScriptContext& context) + if (key >= 0 && key < KEYS_COUNT) { - auto rawKeyIndex = context.GetArgument(0); + // the keys valid, we shouldn't disable it + return false; + } - if (rawKeyIndex >= 0 && rawKeyIndex < KEYS_COUNT) - { - context.SetResult(ioKeyboard_KeyReleased(rawKeyIndex) != 0); - } - else - { - context.SetResult(false); - } - }); + // :( out of bounds + return true; +} - fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_DOWN", [](fx::ScriptContext& context) +template +static void IsRawKeyWrapper(fx::ScriptContext& context) +{ + auto rawKeyIndex = context.GetArgument(0); + + if (!IsRawKeyInvalidOrDisabled(rawKeyIndex)) { - auto rawKeyIndex = context.GetArgument(0); + context.SetResult(fn(rawKeyIndex) != 0); + } + else + { + context.SetResult(false); + } +} - if (rawKeyIndex >= 0 && rawKeyIndex < KEYS_COUNT) - { - context.SetResult(ioKeyboard_KeyDown(rawKeyIndex) != 0); - } - else - { - context.SetResult(false); - } +static HookFunction initFunction([]() +{ +#ifdef IS_RDR3 + uint8_t* location = hook::get_pattern("48 63 05 ? ? ? ? 4C 8D 35 ? ? ? ? 48 83 F0 ? B9"); + ioKeyboardActive = hook::get_address(location, 3, 7); + ioKeyboardKeys = hook::get_address(location + 7, 3, 7); +#else + ioKeyboardActive = hook::get_address(hook::get_pattern("8B 2D ? ? ? ? 48 8B 03"), 2, 6); + ioKeyboardKeys = hook::get_address(hook::get_pattern("48 8D 2D ? ? ? ? 49 C1 E6"), 3, 7); +#endif + + // reset the disabled keys every frame + OnGameFrame.Connect([] + { + disabledKeys.clear(); }); - fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_UP", [](fx::ScriptContext& context) + fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_PRESSED", IsRawKeyWrapper); + fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_RELEASED", IsRawKeyWrapper); + fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_DOWN", IsRawKeyWrapper); + fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_UP", IsRawKeyWrapper); + + fx::ScriptEngine::RegisterNativeHandler("IS_DISABLED_RAW_KEY_PRESSED", IsRawKeyWrapper); + fx::ScriptEngine::RegisterNativeHandler("IS_DISABLED_RAW_KEY_RELEASED", IsRawKeyWrapper); + fx::ScriptEngine::RegisterNativeHandler("IS_DISABLED_RAW_KEY_DOWN", IsRawKeyWrapper); + fx::ScriptEngine::RegisterNativeHandler("IS_DISABLED_RAW_KEY_UP", IsRawKeyWrapper); + + fx::ScriptEngine::RegisterNativeHandler("DISABLE_RAW_KEY_THIS_FRAME", [](fx::ScriptContext& context) { auto rawKeyIndex = context.GetArgument(0); - if (rawKeyIndex >= 0 && rawKeyIndex < KEYS_COUNT) - { - context.SetResult(ioKeyboard_KeyUp(rawKeyIndex) != 0); - } - else + // We only want the bounds check here, we don't care if its already disabled + if (!IsRawKeyInvalidOrDisabled(rawKeyIndex)) { - context.SetResult(false); + disabledKeys.insert(rawKeyIndex); } }); }); diff --git a/code/components/extra-natives-rdr3/component.lua b/code/components/extra-natives-rdr3/component.lua index aecb89fb2b..1813f7ae33 100644 --- a/code/components/extra-natives-rdr3/component.lua +++ b/code/components/extra-natives-rdr3/component.lua @@ -17,6 +17,7 @@ return function() 'components/extra-natives-five/src/PoolTraversalNatives.cpp', 'components/extra-natives-five/src/RadioDSP.cpp', 'components/extra-natives-five/src/NuiAudioSink.cpp', + 'components/extra-natives-five/src/InputNatives.cpp', 'components/gta-core-five/include/GameAudioState.h', 'components/extra-natives-five/include/audDspEffect.h', } diff --git a/code/components/extra-natives-rdr3/src/InputNatives.cpp b/code/components/extra-natives-rdr3/src/InputNatives.cpp deleted file mode 100644 index ce890f4d74..0000000000 --- a/code/components/extra-natives-rdr3/src/InputNatives.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "StdInc.h" - -#include -#include -#include - -constexpr int KEYS_COUNT = 256; - -using keysData = unsigned char[2][KEYS_COUNT]; - -int* ioKeyboardActive = nullptr; -keysData* ioKeyboardKeys = nullptr; - -inline int ioKeyboard_KeyDown(int key) -{ - return (*ioKeyboardKeys)[*ioKeyboardActive][key]; -} - -inline int ioKeyboard_KeyUp(int key) -{ - return !ioKeyboard_KeyDown(key); -} - -inline int ioKeyboard_KeyChanged(int key) -{ - return (*ioKeyboardKeys)[0][key] ^ (*ioKeyboardKeys)[1][key]; -} - -inline int ioKeyboard_KeyPressed(int key) -{ - return (*ioKeyboardKeys)[*ioKeyboardActive][key] & ioKeyboard_KeyChanged(key); -} - -inline int ioKeyboard_KeyReleased(int key) -{ - return (*ioKeyboardKeys)[*ioKeyboardActive ^ 1][key] & ioKeyboard_KeyChanged(key); -} - -static HookFunction initFunction([]() -{ - uint8_t* location = hook::get_pattern("48 63 05 ? ? ? ? 4C 8D 35 ? ? ? ? 48 83 F0 ? B9"); - ioKeyboardActive = hook::get_address(location, 3, 7); - ioKeyboardKeys = hook::get_address(location + 7, 3, 7); - - fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_PRESSED", [](fx::ScriptContext& context) - { - auto rawKeyIndex = context.GetArgument(0); - - if (rawKeyIndex >= 0 && rawKeyIndex < KEYS_COUNT) - { - context.SetResult(ioKeyboard_KeyPressed(rawKeyIndex) != 0); - } - else - { - context.SetResult(false); - } - }); - - fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_RELEASED", [](fx::ScriptContext& context) - { - auto rawKeyIndex = context.GetArgument(0); - - if (rawKeyIndex >= 0 && rawKeyIndex < KEYS_COUNT) - { - context.SetResult(ioKeyboard_KeyReleased(rawKeyIndex) != 0); - } - else - { - context.SetResult(false); - } - }); - - fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_DOWN", [](fx::ScriptContext& context) - { - auto rawKeyIndex = context.GetArgument(0); - - if (rawKeyIndex >= 0 && rawKeyIndex < KEYS_COUNT) - { - context.SetResult(ioKeyboard_KeyDown(rawKeyIndex) != 0); - } - else - { - context.SetResult(false); - } - }); - - fx::ScriptEngine::RegisterNativeHandler("IS_RAW_KEY_UP", [](fx::ScriptContext& context) - { - auto rawKeyIndex = context.GetArgument(0); - - if (rawKeyIndex >= 0 && rawKeyIndex < KEYS_COUNT) - { - context.SetResult(ioKeyboard_KeyUp(rawKeyIndex) != 0); - } - else - { - context.SetResult(false); - } - }); -}); diff --git a/ext/native-decls/DisableRawKeyThisFrame.md b/ext/native-decls/DisableRawKeyThisFrame.md new file mode 100644 index 0000000000..653f5edfdb --- /dev/null +++ b/ext/native-decls/DisableRawKeyThisFrame.md @@ -0,0 +1,33 @@ +--- +ns: CFX +apiset: client +--- +## DISABLE_RAW_KEY_THIS_FRAME + +```c +BOOL DISABLE_RAW_KEY_THIS_FRAME(int rawKeyIndex); +``` + +Disables the specified `rawKeyIndex`, making it not trigger the regular `IS_RAW_KEY_*` natives. + +Virtual key codes can be found [here](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) + +## Parameters +* **rawKeyIndex**: Index of raw key from keyboard. + +## Return value +Returns bool value of down state. + +## Examples +```lua +local KEY_SPACE = 32 +DisableRawKeyThisFrame(KEY_SPACE) +-- This will not get triggered this frame +if IsRawKeyDown(KEY_SPACE) then + print("unreachable :(") +end +-- this will get triggered +if IsDisabledRawKeyDown(KEY_SPACE) then + print("Spacebar is down") +end +``` diff --git a/ext/native-decls/IsDisabledRawKeyDown.md b/ext/native-decls/IsDisabledRawKeyDown.md new file mode 100644 index 0000000000..d7e82c20a0 --- /dev/null +++ b/ext/native-decls/IsDisabledRawKeyDown.md @@ -0,0 +1,26 @@ +--- +ns: CFX +apiset: client +--- +## IS_DISABLED_RAW_KEY_DOWN + +```c +BOOL IS_DISABLED_RAW_KEY_DOWN(int rawKeyIndex); +``` + +Gets if the specified `rawKeyIndex` is pressed down, even if the key is disabled with [DISABLE_RAW_KEY_THIS_FRAME](#_0x8BCF0014). + +Virtual key codes can be found [here](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) + +## Parameters +* **rawKeyIndex**: Index of raw key from keyboard. + +## Return value +Returns bool value of down state. + +## Examples +```lua +if IsDisabledRawKeyDown(32) then -- KEY_SPACE + print("Spacebar is down") +end +``` diff --git a/ext/native-decls/IsDisabledRawKeyPressed.md b/ext/native-decls/IsDisabledRawKeyPressed.md new file mode 100644 index 0000000000..860133e040 --- /dev/null +++ b/ext/native-decls/IsDisabledRawKeyPressed.md @@ -0,0 +1,26 @@ +--- +ns: CFX +apiset: client +--- +## IS_DISABLED_RAW_KEY_PRESSED + +```c +BOOL IS_DISABLED_RAW_KEY_PRESSED(int rawKeyIndex); +``` + +Gets if the specified `rawKeyIndex` is pressed, even if the key is disabled with [DISABLE_RAW_KEY_THIS_FRAME](#_0x8BCF0014). + +Virtual key codes can be found [here](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) + +## Parameters +* **rawKeyIndex**: Index of raw key from keyboard. + +## Return value +Returns bool value of pressed state. + +## Examples +```lua +if IsDisabledRawKeyPressed(32) then -- KEY_SPACE + print("Spacebar pressed") +end +``` diff --git a/ext/native-decls/IsDisabledRawKeyReleased.md b/ext/native-decls/IsDisabledRawKeyReleased.md new file mode 100644 index 0000000000..dfb29fc293 --- /dev/null +++ b/ext/native-decls/IsDisabledRawKeyReleased.md @@ -0,0 +1,26 @@ +--- +ns: CFX +apiset: client +--- +## IS_DISABLED_RAW_KEY_RELEASED + +```c +BOOL IS_DISABLED_RAW_KEY_RELEASED(int rawKeyIndex); +``` + +Gets if the specified `rawKeyIndex` was released, even if the key is disabled with [DISABLE_RAW_KEY_THIS_FRAME](#_0x8BCF0014). + +Virtual key codes can be found [here](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) + +## Parameters +* **rawKeyIndex**: Index of raw key from keyboard. + +## Return value +Returns bool value of released state. + +## Examples +```lua +if IsDisabledRawKeyReleased(32) then -- KEY_SPACE + print("Spacebar released") +end +``` diff --git a/ext/native-decls/IsDisabledRawKeyUp.md b/ext/native-decls/IsDisabledRawKeyUp.md new file mode 100644 index 0000000000..21d38aebe6 --- /dev/null +++ b/ext/native-decls/IsDisabledRawKeyUp.md @@ -0,0 +1,26 @@ +--- +ns: CFX +apiset: client +--- +## IS_DISABLED_RAW_KEY_UP + +```c +BOOL IS_DISABLED_RAW_KEY_UP(int rawKeyIndex); +``` + +Gets if the specified `rawKeyIndex` is up, even if the key is disabled with [DISABLE_RAW_KEY_THIS_FRAME](#_0x8BCF0014). + +Virtual key codes can be found [here](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) + +## Parameters +* **rawKeyIndex**: Index of raw key from keyboard. + +## Return value +Returns bool value of up state. + +## Examples +```lua +if IsDisabledRawKeyUp(32) then -- KEY_SPACE + print("Spacebar is up") +end +``` diff --git a/ext/native-decls/IsRawKeyDown.md b/ext/native-decls/IsRawKeyDown.md index b8e858ec61..7abc5b5e38 100644 --- a/ext/native-decls/IsRawKeyDown.md +++ b/ext/native-decls/IsRawKeyDown.md @@ -8,7 +8,9 @@ apiset: client BOOL IS_RAW_KEY_DOWN(int rawKeyIndex); ``` -Can be used to get state of raw key on keyboard. +Gets if the specified `rawKeyIndex` is pressed down on the keyboard. + +This will not be triggered if the key is disabled with [DISABLE_RAW_KEY_THIS_FRAME](#_0x8BCF0014) Virtual key codes can be found [here](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) diff --git a/ext/native-decls/IsRawKeyPressed.md b/ext/native-decls/IsRawKeyPressed.md index 4f75891528..281921e03d 100644 --- a/ext/native-decls/IsRawKeyPressed.md +++ b/ext/native-decls/IsRawKeyPressed.md @@ -8,7 +8,9 @@ apiset: client BOOL IS_RAW_KEY_PRESSED(int rawKeyIndex); ``` -Can be used to get state of raw key on keyboard. +Gets if the specified `rawKeyIndex` is pressed on the keyboard. + +This will not be triggered if the key is disabled with [DISABLE_RAW_KEY_THIS_FRAME](#_0x8BCF0014) Virtual key codes can be found [here](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) diff --git a/ext/native-decls/IsRawKeyReleased.md b/ext/native-decls/IsRawKeyReleased.md index 505c46a1fb..ce265b7fb7 100644 --- a/ext/native-decls/IsRawKeyReleased.md +++ b/ext/native-decls/IsRawKeyReleased.md @@ -8,7 +8,9 @@ apiset: client BOOL IS_RAW_KEY_RELEASED(int rawKeyIndex); ``` -Can be used to get release state of raw key on keyboard. +Gets if the specified `rawKeyIndex` was just released on the keyboard. + +This will not be triggered if the key is disabled with [DISABLE_RAW_KEY_THIS_FRAME](#_0x8BCF0014) Virtual key codes can be found [here](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) diff --git a/ext/native-decls/IsRawKeyUp.md b/ext/native-decls/IsRawKeyUp.md index d392c2ce35..16cde97af7 100644 --- a/ext/native-decls/IsRawKeyUp.md +++ b/ext/native-decls/IsRawKeyUp.md @@ -8,7 +8,9 @@ apiset: client BOOL IS_RAW_KEY_UP(int rawKeyIndex); ``` -Can be used to get state of raw key on keyboard. +Gets if the specified `rawKeyIndex` is up on the keyboard. + +This will not be triggered if the key is disabled with [DISABLE_RAW_KEY_THIS_FRAME](#_0x8BCF0014) Virtual key codes can be found [here](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes)