diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index 364021c8..3cad580b 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -1033,6 +1033,13 @@ namespace Components void Gamepad::UI_GamepadKeyEvent(const int gamePadIndex, const int key, const bool down) { + // If we are currently capturing a key for menu bind inputs then do not map keys and pass to game + if (*Game::g_waitingForKey) + { + Game::UI_KeyEvent(gamePadIndex, key, down); + return; + } + for (const auto& mapping : controllerMenuKeyMappings) { if (mapping.controllerKey == key) @@ -1777,19 +1784,19 @@ namespace Components return command; } - int Gamepad::Key_GetCommandAssignmentInternal_Hk(const char* cmd, int (*keys)[2]) + int Gamepad::Key_GetCommandAssignmentInternal([[maybe_unused]] int localClientNum, const char* cmd, int (*keys)[2]) { auto keyCount = 0; if (gamePads[0].inUse) { - cmd = GetGamePadCommand(cmd); + const auto gamePadCmd = GetGamePadCommand(cmd); for (auto keyNum = 0; keyNum < Game::K_LAST_KEY; keyNum++) { if (!Key_IsValidGamePadChar(keyNum)) continue; - if (Game::playerKeys[0].keys[keyNum].binding && strcmp(Game::playerKeys[0].keys[keyNum].binding, cmd) == 0) + if (Game::playerKeys[0].keys[keyNum].binding && strcmp(Game::playerKeys[0].keys[keyNum].binding, gamePadCmd) == 0) { (*keys)[keyCount++] = keyNum; @@ -1818,6 +1825,27 @@ namespace Components return keyCount; } + void __declspec(naked) Gamepad::Key_GetCommandAssignmentInternal_Stub() + { + __asm + { + push eax + pushad + + push [esp + 0x20 + 0x4 + 0x8] // keyNums + push [esp + 0x20 + 0x4 + 0x8] // command + push eax // localClientNum + call Key_GetCommandAssignmentInternal + add esp, 0xC + + mov[esp + 0x20], eax + + popad + pop eax + ret + } + } + void Gamepad::CL_KeyEvent_Hk(const int localClientNum, const int key, const int down, const unsigned time) { // A keyboard key has been pressed. Mark controller as unused. @@ -1954,7 +1982,7 @@ namespace Components Utils::Hook(0x48E527, UI_RefreshViewport_Hk, HOOK_CALL).install()->quick(); // Only return gamepad keys when gamepad enabled and only non gamepad keys when not - Utils::Hook(0x5A7A23, Key_GetCommandAssignmentInternal_Hk, HOOK_CALL).install()->quick(); + Utils::Hook(0x5A7890, Key_GetCommandAssignmentInternal_Stub, HOOK_JUMP).install()->quick(); // Add gamepad inputs to remote control (eg predator) handling Utils::Hook(0x5A6D4E, CL_RemoteControlMove_Stub, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Gamepad.hpp b/src/Components/Modules/Gamepad.hpp index a09a4ec6..36c969e9 100644 --- a/src/Components/Modules/Gamepad.hpp +++ b/src/Components/Modules/Gamepad.hpp @@ -192,8 +192,9 @@ namespace Components static void CG_RegisterDvars_Hk(); static const char* GetGamePadCommand(const char* command); - static int Key_GetCommandAssignmentInternal_Hk(const char* cmd, int(*keys)[2]); - static bool IsGamePadInUse(); + static int Key_GetCommandAssignmentInternal(int localClientNum, const char* cmd, int (*keys)[2]); + static void Key_GetCommandAssignmentInternal_Stub(); + static bool IsGamePadInUse(); static void CL_KeyEvent_Hk(int localClientNum, int key, int down, unsigned int time); static int CL_MouseEvent_Hk(int x, int y, int dx, int dy); static bool UI_RefreshViewport_Hk(); diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 4dab19e6..f617cb4e 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -558,6 +558,8 @@ namespace Game int* window_center_x = reinterpret_cast(0x649D638); int* window_center_y = reinterpret_cast(0x649D630); + int* g_waitingForKey = reinterpret_cast(0x63A50FC); + void Sys_LockRead(FastCriticalSection* critSect) { InterlockedIncrement(&critSect->readCount); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index a03f0c85..48f02c0a 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -1158,6 +1158,8 @@ namespace Game extern int* window_center_x; extern int* window_center_y; + extern int* g_waitingForKey; + void Sys_LockRead(FastCriticalSection* critSect); void Sys_UnlockRead(FastCriticalSection* critSect);