Apply gamepad axis rotation to usercmds

This commit is contained in:
Jan 2021-08-23 13:25:14 +02:00
parent 6434526fcb
commit 6043dabc3c
4 changed files with 233 additions and 340 deletions

View File

@ -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,

View File

@ -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);

View File

@ -1274,4 +1274,6 @@ namespace Game
} }
} }
#pragma optimize("", on) #pragma optimize("", on)
clientActive_t* clients = reinterpret_cast<clientActive_t*>(0xB2C698);
} }

View File

@ -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;
} }