diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index c121e936..cbf72ebe 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -179,6 +179,7 @@ namespace Components Dvar::Var Gamepad::aim_input_graph_index; Dvar::Var Gamepad::aim_scale_view_axis; Dvar::Var Gamepad::cl_bypassMouseInput; + Dvar::Var Gamepad::cg_mapLocationSelectionCursorSpeed; Dvar::Var Gamepad::xpadSensitivity; Dvar::Var Gamepad::xpadEarlyTime; @@ -223,7 +224,7 @@ namespace Components __declspec(naked) void Gamepad::MSG_WriteDeltaUsercmdKeyStub() { __asm - { + { // fix stack pointer add esp, 0Ch @@ -241,7 +242,7 @@ namespace Components // return back push 0x60E40E retn - } + } } void Gamepad::ApplyMovement(Game::msg_t* msg, int key, Game::usercmd_s* from, Game::usercmd_s* to) @@ -269,7 +270,7 @@ namespace Components __declspec(naked) void Gamepad::MSG_ReadDeltaUsercmdKeyStub() { __asm - { + { push ebx // to push ebp // from push edi // key @@ -280,13 +281,13 @@ namespace Components // return back push 0x4921BF ret - } + } } __declspec(naked) void Gamepad::MSG_ReadDeltaUsercmdKeyStub2() { __asm - { + { push ebx // to push ebp // from push edi // key @@ -299,7 +300,7 @@ namespace Components push esi push 0x492085 ret - } + } } bool Gamepad::GPad_Check(const int gamePadIndex, const int portIndex) @@ -487,6 +488,77 @@ namespace Components aaGlob.prevButtons = input->buttons; } + + bool Gamepad::CG_HandleLocationSelectionInput_GamePad(const int localClientNum, Game::usercmd_s* cmd) + { + const auto frameTime = static_cast(Game::cgArray[0].frametime) * 0.001f; + const auto mapAspectRatio = Game::cgArray[0].compassMapWorldSize[0] / Game::cgArray[0].compassMapWorldSize[1]; + const auto selectionRequiresAngle = (Game::cgArray[0].predictedPlayerState.locationSelectionInfo & 0x80) != 0; + + auto up = CL_GamepadAxisValue(localClientNum, Game::GPAD_VIRTAXIS_FORWARD); + auto right = CL_GamepadAxisValue(localClientNum, Game::GPAD_VIRTAXIS_SIDE); + auto magnitude = up * up + right * right; + + if(magnitude > 1.0f) + { + magnitude = std::sqrt(magnitude); + up /= magnitude; + right /= magnitude; + } + + Game::cgArray[0].selectedLocation[0] += right * cg_mapLocationSelectionCursorSpeed.get() * frameTime; + Game::cgArray[0].selectedLocation[1] -= up * mapAspectRatio * cg_mapLocationSelectionCursorSpeed.get() * frameTime; + + if(selectionRequiresAngle) + { + const auto yawUp = CL_GamepadAxisValue(localClientNum, Game::GPAD_VIRTAXIS_PITCH); + const auto yawRight = CL_GamepadAxisValue(localClientNum, Game::GPAD_VIRTAXIS_YAW); + + if(std::fabs(yawUp) > 0.0f || std::fabs(yawRight) > 0.0f) + { + Game::vec2_t vec + { + yawUp, + -yawRight + }; + + Game::cgArray[0].selectedLocationAngle = Game::AngleNormalize360(Game::vectoyaw(&vec)); + Game::cgArray[0].selectedAngleLocation[0] = Game::cgArray[0].selectedLocation[0]; + Game::cgArray[0].selectedAngleLocation[1] = Game::cgArray[0].selectedLocation[1]; + } + } + else + { + Game::cgArray[0].selectedAngleLocation[0] = Game::cgArray[0].selectedLocation[0]; + Game::cgArray[0].selectedAngleLocation[1] = Game::cgArray[0].selectedLocation[1]; + } + + return true; + } + + constexpr auto CG_HandleLocationSelectionInput = 0x5A67A0; + __declspec(naked) void Gamepad::CG_HandleLocationSelectionInput_Stub() + { + __asm + { + // Prepare args for our function call + push esi // usercmd + push eax // localClientNum + + call CG_HandleLocationSelectionInput + + test al,al + jz exit_handling + + // Call our function, the args were already prepared earlier + call CG_HandleLocationSelectionInput_GamePad + + exit_handling: + add esp, 0x8 + ret + } + } + bool Gamepad::CG_ShouldUpdateViewAngles(const int localClientNum) { return !Game::Key_IsKeyCatcherActive(localClientNum, Game::KEYCATCH_MASK_ANY) || Game::UI_GetActiveMenu(localClientNum) == Game::UIMENU_SCOREBOARD; @@ -589,7 +661,7 @@ namespace Components __declspec(naked) void Gamepad::CL_MouseMove_Stub() { __asm - { + { // Prepare args for our function call push [esp+0x4] // frametime_base push ebx // cmd @@ -604,7 +676,7 @@ namespace Components add esp,0xC ret - } + } } bool Gamepad::Key_IsValidGamePadChar(const int key) @@ -1188,7 +1260,7 @@ namespace Components void __declspec(naked) Gamepad::Com_WriteConfiguration_Modified_Stub() { __asm - { + { mov eax, [ecx + 0x18] or eax, gamePadBindingsModifiedFlags // Also check for gamePadBindingsModifiedFlags test al, 1 @@ -1202,7 +1274,7 @@ namespace Components endMethod: push 0x60B298 retn - } + } } @@ -1345,6 +1417,7 @@ namespace Components aim_input_graph_index = Dvar::Var("aim_input_graph_index"); aim_scale_view_axis = Dvar::Var("aim_scale_view_axis"); cl_bypassMouseInput = Dvar::Var("cl_bypassMouseInput"); + cg_mapLocationSelectionCursorSpeed = Dvar::Var("cg_mapLocationSelectionCursorSpeed"); } void Gamepad::IN_Init_Hk() @@ -1503,6 +1576,9 @@ namespace Components // Only return gamepad keys when gamepad enabled and only non gamepad keys when not Utils::Hook(0x5A7A23, Key_GetCommandAssignmentInternal_Hk, HOOK_CALL).install()->quick(); + // Add gamepad inputs to location selection (eg airstrike location) handling + Utils::Hook(0x5A6D72, CG_HandleLocationSelectionInput_Stub, HOOK_CALL).install()->quick(); + // Add gamepad inputs to usercmds Utils::Hook(0x5A6DAE, CL_MouseMove_Stub, HOOK_CALL).install()->quick(); } diff --git a/src/Components/Modules/Gamepad.hpp b/src/Components/Modules/Gamepad.hpp index 19243c22..469c9acc 100644 --- a/src/Components/Modules/Gamepad.hpp +++ b/src/Components/Modules/Gamepad.hpp @@ -272,6 +272,7 @@ namespace Components static Dvar::Var aim_input_graph_index; static Dvar::Var aim_scale_view_axis; static Dvar::Var cl_bypassMouseInput; + static Dvar::Var cg_mapLocationSelectionCursorSpeed; static Dvar::Var xpadSensitivity; static Dvar::Var xpadEarlyTime; @@ -294,6 +295,8 @@ namespace Components static void AimAssist_ApplyTurnRates(const Game::AimInput* input, Game::AimOutput* output); static void AimAssist_UpdateGamePadInput(const Game::AimInput* input, Game::AimOutput* output); + static bool CG_HandleLocationSelectionInput_GamePad(int localClientNum, Game::usercmd_s* cmd); + static void CG_HandleLocationSelectionInput_Stub(); static bool CG_ShouldUpdateViewAngles(int localClientNum); static float CL_GamepadAxisValue(int gamePadIndex, Game::GamepadVirtualAxis virtualAxis); static char ClampChar(int value); diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 2d37efde..d9131420 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -339,6 +339,8 @@ namespace Game Win_GetLanguage_t Win_GetLanguage = Win_GetLanguage_t(0x45CBA0); Vec3UnpackUnitVec_t Vec3UnpackUnitVec = Vec3UnpackUnitVec_t(0x45CA90); + vectoyaw_t vectoyaw = vectoyaw_t(0x45AD10); + AngleNormalize360_t AngleNormalize360 = AngleNormalize360_t(0x438DC0); unzClose_t unzClose = unzClose_t(0x41BF20); @@ -441,6 +443,8 @@ namespace Game clientStatic_t* cls = reinterpret_cast(0xA7FE90); + cg_s* cgArray = reinterpret_cast(0x7F0F78); + XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize) { int elSize = DB_GetXAssetSizeHandlers[type](); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 6f46da78..b0b90efb 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -800,6 +800,12 @@ namespace Game typedef void (__cdecl * Vec3UnpackUnitVec_t)(PackedUnitVec, vec3_t *); extern Vec3UnpackUnitVec_t Vec3UnpackUnitVec; + + typedef float(__cdecl* vectoyaw_t)(vec2_t* vec); + extern vectoyaw_t vectoyaw; + + typedef float(__cdecl* AngleNormalize360_t)(float val); + extern AngleNormalize360_t AngleNormalize360; typedef void(__cdecl * unzClose_t)(void* handle); extern unzClose_t unzClose; @@ -903,6 +909,8 @@ namespace Game extern clientStatic_t* cls; + extern cg_s* cgArray; + XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize); void Menu_FreeItemMemory(Game::itemDef_s* item); void Menu_SetNextCursorItem(Game::UiContext* ctx, Game::menuDef_t* currentMenu, int unk = 1); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index a04e3535..80c293bd 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -6141,6 +6141,24 @@ namespace Game float scale; }; + struct __declspec(align(8)) cg_s + { + playerState_s predictedPlayerState; + char _pad0[0x67638]; + int frametime; // + 0x6A754 + char _pad1[0x960C]; // + 0x6A758 + float compassMapWorldSize[2]; // + 0x73D64 + char _pad2[0x74]; // + 0x73D6C + float selectedLocation[2]; // + 0x73DE0 + float selectedLocationAngle; + float selectedAngleLocation[2]; + float selectedLocationPrev[2]; + float selectedLocationAnglePrev; + char _pad3[0x89740]; + }; + + constexpr auto aaaaaaa1 = sizeof(cg_s); + #pragma endregion #ifndef IDA