Apply gamepad axis rotation to usercmds
This commit is contained in:
parent
6434526fcb
commit
6043dabc3c
@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#define XINPUT_SENSITIVITY_MULTIPLIER 4 // Arbitrary value I multiply the xinput senstivity dvar with to get nicer values (0-10 range or something)
|
|
||||||
#define SIGN(d) ((d > 0) - (d < 0))
|
|
||||||
|
|
||||||
namespace Game
|
namespace Game
|
||||||
{
|
{
|
||||||
ButtonToCodeMap_t buttonList[]
|
ButtonToCodeMap_t buttonList[]
|
||||||
@ -45,6 +42,16 @@ namespace Game
|
|||||||
GPAD_INVALID
|
GPAD_INVALID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GamepadPhysicalAxis axisSameStick[GPAD_PHYSAXIS_COUNT]
|
||||||
|
{
|
||||||
|
GPAD_PHYSAXIS_RSTICK_Y,
|
||||||
|
GPAD_PHYSAXIS_RSTICK_X,
|
||||||
|
GPAD_PHYSAXIS_LSTICK_Y,
|
||||||
|
GPAD_PHYSAXIS_LSTICK_X,
|
||||||
|
GPAD_PHYSAXIS_NONE,
|
||||||
|
GPAD_PHYSAXIS_NONE
|
||||||
|
};
|
||||||
|
|
||||||
const char* physicalAxisNames[GPAD_PHYSAXIS_COUNT]
|
const char* physicalAxisNames[GPAD_PHYSAXIS_COUNT]
|
||||||
{
|
{
|
||||||
"A_RSTICK_X",
|
"A_RSTICK_X",
|
||||||
@ -130,6 +137,7 @@ namespace Game
|
|||||||
keyname_t combinedLocalizedKeyNames[VANILLA_KEY_NAME_COUNT + std::extent_v<decltype(extendedLocalizedKeyNames)> + 1];
|
keyname_t combinedLocalizedKeyNames[VANILLA_KEY_NAME_COUNT + std::extent_v<decltype(extendedLocalizedKeyNames)> + 1];
|
||||||
|
|
||||||
PlayerKeyState* playerKeys = reinterpret_cast<PlayerKeyState*>(0xA1B7D0);
|
PlayerKeyState* playerKeys = reinterpret_cast<PlayerKeyState*>(0xA1B7D0);
|
||||||
|
AimAssistGlobals* aaGlobArray = reinterpret_cast<AimAssistGlobals*>(0x7A2110);
|
||||||
keyname_t* vanillaKeyNames = reinterpret_cast<keyname_t*>(0x798580);
|
keyname_t* vanillaKeyNames = reinterpret_cast<keyname_t*>(0x798580);
|
||||||
keyname_t* vanillaLocalizedKeyNames = reinterpret_cast<keyname_t*>(0x798880);
|
keyname_t* vanillaLocalizedKeyNames = reinterpret_cast<keyname_t*>(0x798880);
|
||||||
}
|
}
|
||||||
@ -159,6 +167,7 @@ namespace Components
|
|||||||
Dvar::Var Gamepad::gpad_button_deadzone;
|
Dvar::Var Gamepad::gpad_button_deadzone;
|
||||||
Dvar::Var Gamepad::gpad_button_rstick_deflect_max;
|
Dvar::Var Gamepad::gpad_button_rstick_deflect_max;
|
||||||
Dvar::Var Gamepad::gpad_button_lstick_deflect_max;
|
Dvar::Var Gamepad::gpad_button_lstick_deflect_max;
|
||||||
|
Dvar::Var Gamepad::input_viewSensitivity;
|
||||||
|
|
||||||
Dvar::Var Gamepad::xpadSensitivity;
|
Dvar::Var Gamepad::xpadSensitivity;
|
||||||
Dvar::Var Gamepad::xpadEarlyTime;
|
Dvar::Var Gamepad::xpadEarlyTime;
|
||||||
@ -193,25 +202,6 @@ namespace Components
|
|||||||
{Game::K_APAD_RIGHT, Game::K_RIGHTARROW},
|
{Game::K_APAD_RIGHT, Game::K_RIGHTARROW},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// This should be read from a text file in the players/ folder, most probably / or from config_mp.cfg
|
|
||||||
std::vector<Gamepad::ActionMapping> mappings = {
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_A, "gostand"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_B, "stance"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_X, "usereload"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_Y, "weapnext", false),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_LEFT_SHOULDER, "smoke"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_RIGHT_SHOULDER, "frag"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_LEFT_THUMB, "breath_sprint"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_RIGHT_THUMB, "melee"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_START, "togglemenu", false),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_BACK, "scores"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_DPAD_LEFT, "actionslot 3"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_DPAD_RIGHT, "actionslot 2"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_DPAD_DOWN, "actionslot 1"),
|
|
||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_DPAD_UP, "actionslot 4"),
|
|
||||||
};
|
|
||||||
|
|
||||||
Gamepad::GamePadGlobals::GamePadGlobals()
|
Gamepad::GamePadGlobals::GamePadGlobals()
|
||||||
: axes{},
|
: axes{},
|
||||||
nextScrollTime(0)
|
nextScrollTime(0)
|
||||||
@ -223,132 +213,6 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Same thing
|
|
||||||
|
|
||||||
// void Gamepad::Vibrate(int leftVal, int rightVal)
|
|
||||||
// {
|
|
||||||
// // Create a Vibraton State
|
|
||||||
// XINPUT_VIBRATION Vibration;
|
|
||||||
//
|
|
||||||
// // Zeroise the Vibration
|
|
||||||
// ZeroMemory(&Vibration, sizeof(XINPUT_VIBRATION));
|
|
||||||
//
|
|
||||||
// // Set the Vibration Values
|
|
||||||
// Vibration.wLeftMotorSpeed = leftVal;
|
|
||||||
// Vibration.wRightMotorSpeed = rightVal;
|
|
||||||
//
|
|
||||||
// // Vibrate the controller
|
|
||||||
// XInputSetState(xiPlayerNum, &Vibration);
|
|
||||||
// }
|
|
||||||
|
|
||||||
void Gamepad::CL_GamepadMove(int, Game::usercmd_s* cmd)
|
|
||||||
{
|
|
||||||
auto& gamePad = gamePads[0];
|
|
||||||
|
|
||||||
if (gamePad.enabled)
|
|
||||||
{
|
|
||||||
if (std::fabs(gamePad.sticks[0]) > 0.0f || std::fabs(gamePad.sticks[1]) > 0.0f)
|
|
||||||
{
|
|
||||||
// We check for 0:0 again so we don't overwrite keyboard input in case the user doesn't feel like using their gamepad, even though its plugged in
|
|
||||||
cmd->rightmove = static_cast<char>(gamePad.sticks[0] * static_cast<float>(std::numeric_limits<char>().max()));
|
|
||||||
cmd->forwardmove = static_cast<char>(gamePad.sticks[1] * static_cast<float>(std::numeric_limits<char>().max()));
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool pressingLeftTrigger = gamePad.analogs[0] > TRIGGER_THRESHOLD_F;
|
|
||||||
const bool previouslyPressingLeftTrigger = gamePad.lastAnalogs[0] > TRIGGER_THRESHOLD_F;
|
|
||||||
if (pressingLeftTrigger != previouslyPressingLeftTrigger)
|
|
||||||
{
|
|
||||||
if (pressingLeftTrigger)
|
|
||||||
{
|
|
||||||
Command::Execute("+speed_throw");
|
|
||||||
isADS = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Command::Execute("-speed_throw");
|
|
||||||
isADS = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool pressingRightTrigger = gamePad.analogs[1] > TRIGGER_THRESHOLD_F;
|
|
||||||
const bool previouslyPressingRightTrigger = gamePad.lastAnalogs[1] > TRIGGER_THRESHOLD_F;
|
|
||||||
if (pressingRightTrigger != previouslyPressingRightTrigger)
|
|
||||||
{
|
|
||||||
if (pressingRightTrigger)
|
|
||||||
{
|
|
||||||
Command::Execute("+attack");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Command::Execute("-attack");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buttons (on/off) mappings
|
|
||||||
for (auto& i : mappings)
|
|
||||||
{
|
|
||||||
auto mapping = i;
|
|
||||||
auto action = mapping.action;
|
|
||||||
auto antiAction = mapping.action;
|
|
||||||
|
|
||||||
if (mapping.isReversible)
|
|
||||||
{
|
|
||||||
action = "+" + mapping.action;
|
|
||||||
antiAction = "-" + mapping.action;
|
|
||||||
}
|
|
||||||
else if (mapping.wasPressed)
|
|
||||||
{
|
|
||||||
if (gamePad.digitals & mapping.input)
|
|
||||||
{
|
|
||||||
// Button still pressed, do not send info
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i.wasPressed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gamePad.digitals & mapping.input)
|
|
||||||
{
|
|
||||||
if (mapping.spamWhenHeld || !i.wasPressed)
|
|
||||||
{
|
|
||||||
Command::Execute(action);
|
|
||||||
}
|
|
||||||
i.wasPressed = true;
|
|
||||||
}
|
|
||||||
else if (mapping.isReversible && mapping.wasPressed)
|
|
||||||
{
|
|
||||||
i.wasPressed = false;
|
|
||||||
Command::Execute(antiAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__declspec(naked) void Gamepad::CL_CreateCmdStub()
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
// do xinput!
|
|
||||||
push esi
|
|
||||||
push ebp
|
|
||||||
call CL_GamepadMove
|
|
||||||
add esp, 8h
|
|
||||||
|
|
||||||
// execute code we patched over
|
|
||||||
add esp, 4
|
|
||||||
fld st
|
|
||||||
pop ebx
|
|
||||||
|
|
||||||
// return back
|
|
||||||
push 0x5A6DBF
|
|
||||||
retn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__declspec(naked) void Gamepad::MSG_WriteDeltaUsercmdKeyStub()
|
__declspec(naked) void Gamepad::MSG_WriteDeltaUsercmdKeyStub()
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
@ -431,151 +295,6 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Gamepad::unk_CheckKeyHook(int localClientNum, Game::keyNum_t keyCode)
|
|
||||||
{
|
|
||||||
const auto& gamePad = gamePads[0];
|
|
||||||
|
|
||||||
if (gamePad.enabled)
|
|
||||||
{
|
|
||||||
if (keyCode == Game::keyNum_t::K_MOUSE2)
|
|
||||||
{
|
|
||||||
const bool pressingLeftTrigger = gamePad.analogs[0] > TRIGGER_THRESHOLD_F;
|
|
||||||
const bool previouslyPressingLeftTrigger = gamePad.lastAnalogs[0] > TRIGGER_THRESHOLD_F;
|
|
||||||
if (pressingLeftTrigger != previouslyPressingLeftTrigger)
|
|
||||||
{
|
|
||||||
if (pressingLeftTrigger)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Utils::Hook::Call<int(int, Game::keyNum_t)>(0x48B2D0)(localClientNum, keyCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gamepad::MouseOverride(Game::clientActive_t* clientActive, float* mx, float* my)
|
|
||||||
{
|
|
||||||
CL_GetMouseMovementCl(clientActive, mx, my);
|
|
||||||
|
|
||||||
const auto& gamePad = gamePads[0];
|
|
||||||
|
|
||||||
if (gamePad.enabled)
|
|
||||||
{
|
|
||||||
float viewSensitivityMultiplier = xpadSensitivity.get<float>() * XINPUT_SENSITIVITY_MULTIPLIER;
|
|
||||||
|
|
||||||
float lockedSensitivityMultiplier = xpadEarlyMultiplier.get<float>();
|
|
||||||
float generalXSensitivityMultiplier = xpadHorizontalMultiplier.get<float>();
|
|
||||||
float generalYSensitivityMultiplier = xpadVerticalMultiplier.get<float>();
|
|
||||||
std::chrono::milliseconds msBeforeUnlockingSensitivity = std::chrono::milliseconds(xpadEarlyTime.get<int>());
|
|
||||||
|
|
||||||
float viewStickX = gamePad.sticks[2];
|
|
||||||
float viewStickY = gamePad.sticks[3];
|
|
||||||
|
|
||||||
// Gamepad horizontal acceleration on view
|
|
||||||
if (abs(viewStickX) > 0.80f)
|
|
||||||
{
|
|
||||||
if (!isHoldingMaxLookX)
|
|
||||||
{
|
|
||||||
isHoldingMaxLookX = true;
|
|
||||||
timeAtFirstHeldMaxLookX = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::chrono::milliseconds hasBeenHoldingLeftXForMs = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()) -
|
|
||||||
timeAtFirstHeldMaxLookX;
|
|
||||||
#ifdef STEP_SENSITIVITY
|
|
||||||
if (hasBeenHoldingLeftXForMs < msBeforeUnlockingSensitivity) {
|
|
||||||
viewStickX *= lockedSensitivityMultiplier;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
float coeff = std::clamp(hasBeenHoldingLeftXForMs.count() / (float)msBeforeUnlockingSensitivity.count(), 0.0F, 1.0F);
|
|
||||||
viewStickX *= lockedSensitivityMultiplier + coeff * (1.0f - lockedSensitivityMultiplier);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isHoldingMaxLookX = false;
|
|
||||||
timeAtFirstHeldMaxLookX = 0ms;
|
|
||||||
viewStickX *= lockedSensitivityMultiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
float adsMultiplier = 1.0f;
|
|
||||||
|
|
||||||
auto ps = &clientActive->snap.ps;
|
|
||||||
|
|
||||||
// DO NOT use clientActive->usingAds ! It only works for toggle ADS
|
|
||||||
if (PM_IsAdsAllowed(ps) && isADS)
|
|
||||||
{
|
|
||||||
adsMultiplier = xpadAdsMultiplier.get<float>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (viewStickX != 0 || viewStickY != 0)
|
|
||||||
{
|
|
||||||
*(my) = viewStickX * viewSensitivityMultiplier * generalXSensitivityMultiplier * adsMultiplier;
|
|
||||||
*(mx) = -viewStickY * viewSensitivityMultiplier * generalYSensitivityMultiplier * adsMultiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handling killstreaks
|
|
||||||
const bool pressingRightTrigger = gamePad.analogs[1] > TRIGGER_THRESHOLD_F;
|
|
||||||
const bool previouslyPressingRightTrigger = gamePad.lastAnalogs[1] > TRIGGER_THRESHOLD_F;
|
|
||||||
if (pressingRightTrigger != previouslyPressingRightTrigger)
|
|
||||||
{
|
|
||||||
bool* isInPredator = reinterpret_cast<bool*>(0x8EE3B8);
|
|
||||||
|
|
||||||
if (pressingRightTrigger)
|
|
||||||
{
|
|
||||||
Utils::Hook::Set(0xA1C4F4, Game::LOC_SEL_INPUT_CONFIRM);
|
|
||||||
if (*isInPredator)
|
|
||||||
{
|
|
||||||
// Yea, that's how we boost
|
|
||||||
// Command::execute is sync by default so the predator event gets fired properly
|
|
||||||
Command::Execute("+attack");
|
|
||||||
Command::Execute("-attack");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Game -> Client DLL
|
|
||||||
__declspec(naked) void CL_GetMouseMovementStub()
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push edx;
|
|
||||||
push ecx;
|
|
||||||
push eax;
|
|
||||||
call Gamepad::MouseOverride;
|
|
||||||
add esp, 0xC;
|
|
||||||
ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client DLL -> Game
|
|
||||||
void Gamepad::CL_GetMouseMovementCl(Game::clientActive_t* result, float* mx, float* my)
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push ebx;
|
|
||||||
push ecx;
|
|
||||||
push edx;
|
|
||||||
mov eax, result;
|
|
||||||
mov ecx, mx;
|
|
||||||
mov edx, my;
|
|
||||||
mov ebx, 5A60E0h;
|
|
||||||
call ebx;
|
|
||||||
pop edx;
|
|
||||||
pop ecx;
|
|
||||||
pop ebx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Gamepad::GPad_Check(const int gamePadIndex, const int portIndex)
|
bool Gamepad::GPad_Check(const int gamePadIndex, const int portIndex)
|
||||||
{
|
{
|
||||||
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
||||||
@ -610,6 +329,111 @@ namespace Components
|
|||||||
|| key >= Game::K_FIRSTGAMEPADBUTTON_RANGE_3 && key <= Game::K_LASTGAMEPADBUTTON_RANGE_3;
|
|| key >= Game::K_FIRSTGAMEPADBUTTON_RANGE_3 && key <= Game::K_LASTGAMEPADBUTTON_RANGE_3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Gamepad::CL_GamepadAxisValue(const int gamePadIndex, const Game::GamepadVirtualAxis virtualAxis)
|
||||||
|
{
|
||||||
|
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
||||||
|
assert(virtualAxis > Game::GPAD_VIRTAXIS_NONE && virtualAxis < Game::GPAD_VIRTAXIS_COUNT);
|
||||||
|
const auto& gamePadGlobal = gamePadGlobals[gamePadIndex];
|
||||||
|
|
||||||
|
const auto& [physicalAxis, mapType] = gamePadGlobal.axes.virtualAxes[virtualAxis];
|
||||||
|
|
||||||
|
if (physicalAxis <= Game::GPAD_PHYSAXIS_NONE || physicalAxis >= Game::GPAD_PHYSAXIS_COUNT)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
auto axisDeflection = gamePadGlobal.axes.axesValues[physicalAxis];
|
||||||
|
|
||||||
|
if (mapType == Game::GPAD_MAP_SQUARED)
|
||||||
|
{
|
||||||
|
const auto otherAxisSameStick = Game::axisSameStick[physicalAxis];
|
||||||
|
|
||||||
|
float otherAxisDeflection;
|
||||||
|
if (otherAxisSameStick <= Game::GPAD_PHYSAXIS_NONE || otherAxisSameStick >= Game::GPAD_PHYSAXIS_COUNT)
|
||||||
|
otherAxisDeflection = 0.0f;
|
||||||
|
else
|
||||||
|
otherAxisDeflection = gamePadGlobal.axes.axesValues[otherAxisSameStick];
|
||||||
|
|
||||||
|
axisDeflection = std::sqrt(axisDeflection * axisDeflection + otherAxisDeflection * otherAxisDeflection) * axisDeflection;
|
||||||
|
}
|
||||||
|
|
||||||
|
return axisDeflection;
|
||||||
|
}
|
||||||
|
|
||||||
|
char Gamepad::ClampChar(const int value)
|
||||||
|
{
|
||||||
|
return static_cast<char>(std::clamp<int>(value, std::numeric_limits<char>::min(), std::numeric_limits<char>::max()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gamepad::CL_GamepadMove(const int gamePadIndex, Game::usercmd_s* cmd, const float frame_time_base)
|
||||||
|
{
|
||||||
|
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
||||||
|
auto& gamePad = gamePads[gamePadIndex];
|
||||||
|
auto& gamePadGlobal = gamePadGlobals[gamePadIndex];
|
||||||
|
|
||||||
|
if (!gpad_enabled.get<bool>() || !gamePad.enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto pitch = CL_GamepadAxisValue(gamePadIndex, Game::GPAD_VIRTAXIS_PITCH);
|
||||||
|
if (!Dvar::Var("input_invertPitch").get<bool>())
|
||||||
|
pitch *= -1;
|
||||||
|
|
||||||
|
auto yaw = -CL_GamepadAxisValue(gamePadIndex, Game::GPAD_VIRTAXIS_YAW);
|
||||||
|
auto forward = CL_GamepadAxisValue(gamePadIndex, Game::GPAD_VIRTAXIS_FORWARD);
|
||||||
|
auto side = CL_GamepadAxisValue(gamePadIndex, Game::GPAD_VIRTAXIS_SIDE);
|
||||||
|
auto attack = CL_GamepadAxisValue(gamePadIndex, Game::GPAD_VIRTAXIS_ATTACK);
|
||||||
|
auto moveScale = static_cast<float>(std::numeric_limits<char>::max());
|
||||||
|
|
||||||
|
if (std::fabs(side) > 0.0f || std::fabs(forward) > 0.0f)
|
||||||
|
{
|
||||||
|
const auto length = std::fabs(side) <= std::fabs(forward)
|
||||||
|
? side / forward
|
||||||
|
: forward / side;
|
||||||
|
moveScale = std::sqrt((length * length) + 1.0f) * moveScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto forwardMove = static_cast<int>(std::floor(forward * moveScale));
|
||||||
|
const auto rightMove = static_cast<int>(std::floor(side * moveScale));
|
||||||
|
|
||||||
|
const auto sensitivity = input_viewSensitivity.get<float>();
|
||||||
|
pitch *= sensitivity;
|
||||||
|
yaw *= sensitivity;
|
||||||
|
|
||||||
|
if (Game::clients[0].cgameMaxPitchSpeed > 0 && Game::clients[0].cgameMaxPitchSpeed < std::fabs(pitch))
|
||||||
|
pitch = std::signbit(pitch) ? -Game::clients[0].cgameMaxPitchSpeed : Game::clients[0].cgameMaxPitchSpeed;
|
||||||
|
if (Game::clients[0].cgameMaxYawSpeed > 0 && Game::clients[0].cgameMaxYawSpeed < std::fabs(yaw))
|
||||||
|
yaw = std::signbit(yaw) ? -Game::clients[0].cgameMaxYawSpeed : Game::clients[0].cgameMaxYawSpeed;
|
||||||
|
|
||||||
|
|
||||||
|
Game::clients[0].clViewangles[0] += pitch;
|
||||||
|
Game::clients[0].clViewangles[1] += yaw;
|
||||||
|
|
||||||
|
cmd->rightmove = ClampChar(cmd->rightmove + rightMove);
|
||||||
|
cmd->forwardmove = ClampChar(cmd->forwardmove + forwardMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto CL_MouseMove = 0x5A6240;
|
||||||
|
|
||||||
|
__declspec(naked) void Gamepad::CL_MouseMove_Stub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
// Prepare args for our function call
|
||||||
|
push [esp+0x4] // frametime_base
|
||||||
|
push ebx // cmd
|
||||||
|
push eax // localClientNum
|
||||||
|
|
||||||
|
push [esp+0x8] // restore frametime_base on the stack
|
||||||
|
call CL_MouseMove
|
||||||
|
add esp,4
|
||||||
|
|
||||||
|
// Call our function, the args were already prepared earlier
|
||||||
|
call CL_GamepadMove
|
||||||
|
add esp,0xC
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Gamepad::CL_GamepadResetMenuScrollTime(const int gamePadIndex, const int key, const bool down, const unsigned time)
|
void Gamepad::CL_GamepadResetMenuScrollTime(const int gamePadIndex, const int key, const bool down, const unsigned time)
|
||||||
{
|
{
|
||||||
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
||||||
@ -1171,7 +995,7 @@ namespace Components
|
|||||||
|
|
||||||
Game::FS_Printf(handle, "unbindallaxis\n");
|
Game::FS_Printf(handle, "unbindallaxis\n");
|
||||||
|
|
||||||
for(auto virtualAxisIndex = 0u; virtualAxisIndex < Game::GPAD_VIRTAXIS_COUNT; virtualAxisIndex++)
|
for (auto virtualAxisIndex = 0u; virtualAxisIndex < Game::GPAD_VIRTAXIS_COUNT; virtualAxisIndex++)
|
||||||
{
|
{
|
||||||
const auto& axisMapping = gamePadGlobal.axes.virtualAxes[virtualAxisIndex];
|
const auto& axisMapping = gamePadGlobal.axes.virtualAxes[virtualAxisIndex];
|
||||||
if (axisMapping.physicalAxis <= Game::GPAD_PHYSAXIS_NONE || axisMapping.physicalAxis >= Game::GPAD_PHYSAXIS_COUNT
|
if (axisMapping.physicalAxis <= Game::GPAD_PHYSAXIS_NONE || axisMapping.physicalAxis >= Game::GPAD_PHYSAXIS_COUNT
|
||||||
@ -1343,6 +1167,8 @@ namespace Components
|
|||||||
gpad_button_deadzone = Dvar::Register<float>("gpad_button_deadzone", 0.13f, 0.0f, 1.0f, 0, "Game pad button deadzone threshhold");
|
gpad_button_deadzone = Dvar::Register<float>("gpad_button_deadzone", 0.13f, 0.0f, 1.0f, 0, "Game pad button deadzone threshhold");
|
||||||
gpad_button_lstick_deflect_max = Dvar::Register<float>("gpad_button_lstick_deflect_max", 1.0f, 0.0f, 1.0f, 0, "Game pad maximum pad stick pressed value");
|
gpad_button_lstick_deflect_max = Dvar::Register<float>("gpad_button_lstick_deflect_max", 1.0f, 0.0f, 1.0f, 0, "Game pad maximum pad stick pressed value");
|
||||||
gpad_button_rstick_deflect_max = Dvar::Register<float>("gpad_button_rstick_deflect_max", 1.0f, 0.0f, 1.0f, 0, "Game pad maximum pad stick pressed value");
|
gpad_button_rstick_deflect_max = Dvar::Register<float>("gpad_button_rstick_deflect_max", 1.0f, 0.0f, 1.0f, 0, "Game pad maximum pad stick pressed value");
|
||||||
|
|
||||||
|
input_viewSensitivity = Dvar::Register<float>("input_viewSensitivity", 1.0f, 0.0001f, 5.0f, Game::DVAR_FLAG_SAVED, "View Sensitivity");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gamepad::IN_Init_Hk()
|
void Gamepad::IN_Init_Hk()
|
||||||
@ -1361,10 +1187,10 @@ namespace Components
|
|||||||
{
|
{
|
||||||
for (auto keyNum = 0; keyNum < Game::K_LAST_KEY; keyNum++)
|
for (auto keyNum = 0; keyNum < Game::K_LAST_KEY; keyNum++)
|
||||||
{
|
{
|
||||||
if(!Key_IsValidGamePadChar(keyNum))
|
if (!Key_IsValidGamePadChar(keyNum))
|
||||||
continue;
|
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, cmd) == 0)
|
||||||
{
|
{
|
||||||
(*keys)[keyCount++] = keyNum;
|
(*keys)[keyCount++] = keyNum;
|
||||||
|
|
||||||
@ -1441,11 +1267,12 @@ namespace Components
|
|||||||
{
|
{
|
||||||
memcpy(Game::combinedKeyNames, Game::vanillaKeyNames, sizeof(Game::keyname_t) * Game::VANILLA_KEY_NAME_COUNT);
|
memcpy(Game::combinedKeyNames, Game::vanillaKeyNames, sizeof(Game::keyname_t) * Game::VANILLA_KEY_NAME_COUNT);
|
||||||
memcpy(&Game::combinedKeyNames[Game::VANILLA_KEY_NAME_COUNT], Game::extendedKeyNames, sizeof(Game::keyname_t) * std::extent_v<decltype(Game::extendedKeyNames)>);
|
memcpy(&Game::combinedKeyNames[Game::VANILLA_KEY_NAME_COUNT], Game::extendedKeyNames, sizeof(Game::keyname_t) * std::extent_v<decltype(Game::extendedKeyNames)>);
|
||||||
Game::combinedKeyNames[std::extent_v<decltype(Game::combinedKeyNames)> -1] = { nullptr, 0 };
|
Game::combinedKeyNames[std::extent_v<decltype(Game::combinedKeyNames)> - 1] = {nullptr, 0};
|
||||||
|
|
||||||
memcpy(Game::combinedLocalizedKeyNames, Game::vanillaLocalizedKeyNames, sizeof(Game::keyname_t) * Game::VANILLA_LOCALIZED_KEY_NAME_COUNT);
|
memcpy(Game::combinedLocalizedKeyNames, Game::vanillaLocalizedKeyNames, sizeof(Game::keyname_t) * Game::VANILLA_LOCALIZED_KEY_NAME_COUNT);
|
||||||
memcpy(&Game::combinedLocalizedKeyNames[Game::VANILLA_LOCALIZED_KEY_NAME_COUNT], Game::extendedLocalizedKeyNames, sizeof(Game::keyname_t) * std::extent_v<decltype(Game::extendedLocalizedKeyNames)>);
|
memcpy(&Game::combinedLocalizedKeyNames[Game::VANILLA_LOCALIZED_KEY_NAME_COUNT], Game::extendedLocalizedKeyNames,
|
||||||
Game::combinedLocalizedKeyNames[std::extent_v<decltype(Game::combinedLocalizedKeyNames)> -1] = { nullptr, 0 };
|
sizeof(Game::keyname_t) * std::extent_v<decltype(Game::extendedLocalizedKeyNames)>);
|
||||||
|
Game::combinedLocalizedKeyNames[std::extent_v<decltype(Game::combinedLocalizedKeyNames)> - 1] = {nullptr, 0};
|
||||||
|
|
||||||
Utils::Hook::Set<Game::keyname_t*>(0x4A780A, Game::combinedKeyNames);
|
Utils::Hook::Set<Game::keyname_t*>(0x4A780A, Game::combinedKeyNames);
|
||||||
Utils::Hook::Set<Game::keyname_t*>(0x4A7810, Game::combinedKeyNames);
|
Utils::Hook::Set<Game::keyname_t*>(0x4A7810, Game::combinedKeyNames);
|
||||||
@ -1474,7 +1301,6 @@ namespace Components
|
|||||||
|
|
||||||
// Also rewrite configuration when gamepad config is dirty
|
// Also rewrite configuration when gamepad config is dirty
|
||||||
Utils::Hook(0x60B264, Com_WriteConfiguration_Modified_Stub, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x60B264, Com_WriteConfiguration_Modified_Stub, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
Utils::Hook(0x60B223, Key_WriteBindings_Hk, HOOK_CALL).install()->quick();
|
Utils::Hook(0x60B223, Key_WriteBindings_Hk, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
CreateKeyNameMap();
|
CreateKeyNameMap();
|
||||||
@ -1505,6 +1331,9 @@ namespace Components
|
|||||||
//Utils::Hook(0x5A6816, CL_GetMouseMovementStub, HOOK_CALL).install()->quick();
|
//Utils::Hook(0x5A6816, CL_GetMouseMovementStub, HOOK_CALL).install()->quick();
|
||||||
//Utils::Hook(0x5A6829, unk_CheckKeyHook, HOOK_CALL).install()->quick();
|
//Utils::Hook(0x5A6829, unk_CheckKeyHook, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
|
// Add gamepad inputs to usercmds
|
||||||
|
Utils::Hook(0x5A6DAE, CL_MouseMove_Stub, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
xpadSensitivity = Dvar::Register<float>("xpad_sensitivity", 1.9f, 0.1f, 10.0f, Game::DVAR_FLAG_SAVED, "View sensitivity for XInput-compatible gamepads");
|
xpadSensitivity = Dvar::Register<float>("xpad_sensitivity", 1.9f, 0.1f, 10.0f, Game::DVAR_FLAG_SAVED, "View sensitivity for XInput-compatible gamepads");
|
||||||
xpadEarlyTime = Dvar::Register<int>("xpad_early_time", 130, 0, 1000, Game::DVAR_FLAG_SAVED, "Time (in milliseconds) of reduced view sensitivity");
|
xpadEarlyTime = Dvar::Register<int>("xpad_early_time", 130, 0, 1000, Game::DVAR_FLAG_SAVED, "Time (in milliseconds) of reduced view sensitivity");
|
||||||
xpadEarlyMultiplier = Dvar::Register<float>("xpad_early_multiplier", 0.25f, 0.01f, 1.0f, Game::DVAR_FLAG_SAVED,
|
xpadEarlyMultiplier = Dvar::Register<float>("xpad_early_multiplier", 0.25f, 0.01f, 1.0f, Game::DVAR_FLAG_SAVED,
|
||||||
|
@ -114,6 +114,89 @@ namespace Game
|
|||||||
float axesValues[GPAD_PHYSAXIS_COUNT];
|
float axesValues[GPAD_PHYSAXIS_COUNT];
|
||||||
GamepadVirtualAxisMapping virtualAxes[GPAD_VIRTAXIS_COUNT];
|
GamepadVirtualAxisMapping virtualAxes[GPAD_VIRTAXIS_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AimAssistPlayerState
|
||||||
|
{
|
||||||
|
float velocity[3];
|
||||||
|
int eFlags;
|
||||||
|
int linkFlags;
|
||||||
|
int pm_flags;
|
||||||
|
int weapFlags;
|
||||||
|
int weaponState;
|
||||||
|
float fWeaponPosFrac;
|
||||||
|
int weapIndex;
|
||||||
|
bool hasAmmo;
|
||||||
|
bool isDualWielding;
|
||||||
|
bool isThirdPerson;
|
||||||
|
bool isExtendedMelee;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AimTweakables
|
||||||
|
{
|
||||||
|
float slowdownRegionWidth;
|
||||||
|
float slowdownRegionHeight;
|
||||||
|
float autoAimRegionWidth;
|
||||||
|
float autoAimRegionHeight;
|
||||||
|
float autoMeleeRegionWidth;
|
||||||
|
float autoMeleeRegionHeight;
|
||||||
|
float lockOnRegionWidth;
|
||||||
|
float lockOnRegionHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AimScreenTarget
|
||||||
|
{
|
||||||
|
int entIndex;
|
||||||
|
float clipMins[2];
|
||||||
|
float clipMaxs[2];
|
||||||
|
float aimPos[3];
|
||||||
|
float velocity[3];
|
||||||
|
float distSqr;
|
||||||
|
float crosshairDistSqr;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AutoMeleeState
|
||||||
|
{
|
||||||
|
AIM_MELEE_STATE_OFF = 0x0,
|
||||||
|
AIM_MELEE_STATE_TARGETED = 0x1,
|
||||||
|
AIM_MELEE_STATE_UPDATING = 0x2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __declspec(align(16)) AimAssistGlobals
|
||||||
|
{
|
||||||
|
AimAssistPlayerState ps;
|
||||||
|
__declspec(align(8)) float screenMtx[4][4];
|
||||||
|
float invScreenMtx[4][4];
|
||||||
|
bool initialized;
|
||||||
|
int prevButtons;
|
||||||
|
AimTweakables tweakables;
|
||||||
|
float eyeOrigin[3];
|
||||||
|
float viewOrigin[3];
|
||||||
|
float viewAngles[3];
|
||||||
|
float viewAxis[3][3];
|
||||||
|
float fovTurnRateScale;
|
||||||
|
float fovScaleInv;
|
||||||
|
float adsLerp;
|
||||||
|
float pitchDelta;
|
||||||
|
float yawDelta;
|
||||||
|
float screenWidth;
|
||||||
|
float screenHeight;
|
||||||
|
AimScreenTarget screenTargets[64];
|
||||||
|
int screenTargetCount;
|
||||||
|
int autoAimTargetEnt;
|
||||||
|
bool autoAimPressed;
|
||||||
|
bool autoAimActive;
|
||||||
|
float autoAimPitch;
|
||||||
|
float autoAimPitchTarget;
|
||||||
|
float autoAimYaw;
|
||||||
|
float autoAimYawTarget;
|
||||||
|
AutoMeleeState autoMeleeState;
|
||||||
|
int autoMeleeTargetEnt;
|
||||||
|
float autoMeleePitch;
|
||||||
|
float autoMeleePitchTarget;
|
||||||
|
float autoMeleeYaw;
|
||||||
|
float autoMeleeYawTarget;
|
||||||
|
int lockOnTargetEnt;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Components
|
namespace Components
|
||||||
@ -153,23 +236,6 @@ namespace Components
|
|||||||
GamePadGlobals();
|
GamePadGlobals();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ActionMapping
|
|
||||||
{
|
|
||||||
int input;
|
|
||||||
std::string action;
|
|
||||||
bool isReversible;
|
|
||||||
bool wasPressed = false;
|
|
||||||
bool spamWhenHeld = false;
|
|
||||||
|
|
||||||
ActionMapping(int input, std::string action, bool isReversible = true, bool spamWhenHeld = false)
|
|
||||||
{
|
|
||||||
this->action = action;
|
|
||||||
this->isReversible = isReversible;
|
|
||||||
this->input = input;
|
|
||||||
this->spamWhenHeld = spamWhenHeld;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static GamePad gamePads[Game::MAX_GAMEPADS];
|
static GamePad gamePads[Game::MAX_GAMEPADS];
|
||||||
static GamePadGlobals gamePadGlobals[Game::MAX_GAMEPADS];
|
static GamePadGlobals gamePadGlobals[Game::MAX_GAMEPADS];
|
||||||
@ -200,6 +266,11 @@ namespace Components
|
|||||||
static Dvar::Var gpad_button_deadzone;
|
static Dvar::Var gpad_button_deadzone;
|
||||||
static Dvar::Var gpad_button_rstick_deflect_max;
|
static Dvar::Var gpad_button_rstick_deflect_max;
|
||||||
static Dvar::Var gpad_button_lstick_deflect_max;
|
static Dvar::Var gpad_button_lstick_deflect_max;
|
||||||
|
static Dvar::Var input_viewSensitivity;
|
||||||
|
static Dvar::Var aim_turnrate_pitch;
|
||||||
|
static Dvar::Var aim_turnrate_pitch_ads;
|
||||||
|
static Dvar::Var aim_turnrate_yaw;
|
||||||
|
static Dvar::Var aim_turnrate_yaw_ads;
|
||||||
|
|
||||||
static Dvar::Var xpadSensitivity;
|
static Dvar::Var xpadSensitivity;
|
||||||
static Dvar::Var xpadEarlyTime;
|
static Dvar::Var xpadEarlyTime;
|
||||||
@ -208,18 +279,6 @@ namespace Components
|
|||||||
static Dvar::Var xpadVerticalMultiplier;
|
static Dvar::Var xpadVerticalMultiplier;
|
||||||
static Dvar::Var xpadAdsMultiplier;
|
static Dvar::Var xpadAdsMultiplier;
|
||||||
|
|
||||||
static void CL_GetMouseMovementCl(Game::clientActive_t* result, float* mx, float* my);
|
|
||||||
static int unk_CheckKeyHook(int localClientNum, Game::keyNum_t keyCode);
|
|
||||||
|
|
||||||
static void MouseOverride(Game::clientActive_t* clientActive, float* my, float* mx);
|
|
||||||
static void Vibrate(int leftVal = 0, int rightVal = 0);
|
|
||||||
|
|
||||||
static void CL_FrameStub();
|
|
||||||
static void PollXInputDevices();
|
|
||||||
|
|
||||||
static void CL_CreateCmdStub();
|
|
||||||
static void CL_GamepadMove(int, Game::usercmd_s*);
|
|
||||||
|
|
||||||
static void MSG_WriteDeltaUsercmdKeyStub();
|
static void MSG_WriteDeltaUsercmdKeyStub();
|
||||||
|
|
||||||
static void ApplyMovement(Game::msg_t* msg, int key, Game::usercmd_s* from, Game::usercmd_s* to);
|
static void ApplyMovement(Game::msg_t* msg, int key, Game::usercmd_s* from, Game::usercmd_s* to);
|
||||||
@ -227,11 +286,12 @@ namespace Components
|
|||||||
static void MSG_ReadDeltaUsercmdKeyStub();
|
static void MSG_ReadDeltaUsercmdKeyStub();
|
||||||
static void MSG_ReadDeltaUsercmdKeyStub2();
|
static void MSG_ReadDeltaUsercmdKeyStub2();
|
||||||
|
|
||||||
static void GetLeftStick01Value(XINPUT_STATE* xiState, float& x, float& y);
|
static bool Key_IsValidGamePadChar(int key);
|
||||||
static void GetRightStick01Value(XINPUT_STATE* xiState, float& x, float& y);
|
|
||||||
static void GamepadStickTo01(SHORT value, SHORT deadzone, float& output01);
|
|
||||||
|
|
||||||
static bool Key_IsValidGamePadChar(const int key);
|
static float CL_GamepadAxisValue(int gamePadIndex, Game::GamepadVirtualAxis virtualAxis);
|
||||||
|
static char ClampChar(int value);
|
||||||
|
static void CL_GamepadMove(int gamePadIndex, Game::usercmd_s* cmd, float frame_time_base);
|
||||||
|
static void CL_MouseMove_Stub();
|
||||||
|
|
||||||
static void CL_GamepadResetMenuScrollTime(int gamePadIndex, int key, bool down, unsigned int time);
|
static void CL_GamepadResetMenuScrollTime(int gamePadIndex, int key, bool down, unsigned int time);
|
||||||
static bool CL_CheckForIgnoreDueToRepeat(int gamePadIndex, int key, int repeatCount, unsigned int time);
|
static bool CL_CheckForIgnoreDueToRepeat(int gamePadIndex, int key, int repeatCount, unsigned int time);
|
||||||
|
@ -1274,4 +1274,6 @@ namespace Game
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma optimize("", on)
|
#pragma optimize("", on)
|
||||||
|
|
||||||
|
clientActive_t* clients = reinterpret_cast<clientActive_t*>(0xB2C698);
|
||||||
}
|
}
|
||||||
|
@ -956,4 +956,6 @@ namespace Game
|
|||||||
void R_AddDebugBounds(float* color, Bounds* b, const float(*quat)[4]);
|
void R_AddDebugBounds(float* color, Bounds* b, const float(*quat)[4]);
|
||||||
|
|
||||||
Glyph* R_GetCharacterGlyph(Font_s* font, unsigned int letter);
|
Glyph* R_GetCharacterGlyph(Font_s* font, unsigned int letter);
|
||||||
|
|
||||||
|
extern clientActive_t* clients;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user