Add binding commands to keys for controllers

This commit is contained in:
Jan 2021-08-22 00:04:30 +02:00
parent 2decfa2c45
commit 6d598df56d
5 changed files with 539 additions and 48 deletions

View File

@ -110,6 +110,7 @@ namespace Components
}
}
void Dvar::Var::setRaw(int integer)
{
if (this->dvar)
@ -126,6 +127,14 @@ namespace Components
}
}
void Dvar::Var::setRaw(bool value)
{
if (this->dvar)
{
this->dvar->current.enabled = value;
}
}
template<> static Dvar::Var Dvar::Register(const char* name, bool value, Dvar::Flag flag, const char* description)
{
return Game::Dvar_RegisterBool(name, value, flag.val, description);

View File

@ -35,6 +35,7 @@ namespace Components
// TODO: Add others
void setRaw(int integer);
void setRaw(float value);
void setRaw(bool value);
private:
Game::dvar_t* dvar;

View File

@ -5,9 +5,76 @@
#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
{
ButtonToCodeMap_t buttonList[]
{
{GPAD_X, K_BUTTON_X},
{GPAD_A, K_BUTTON_A},
{GPAD_B, K_BUTTON_B},
{GPAD_Y, K_BUTTON_Y},
{GPAD_L_TRIG, K_BUTTON_LTRIG},
{GPAD_R_TRIG, K_BUTTON_RTRIG},
{GPAD_L_SHLDR, K_BUTTON_LSHLDR},
{GPAD_R_SHLDR, K_BUTTON_RSHLDR},
{GPAD_START, K_BUTTON_START},
{GPAD_BACK, K_BUTTON_BACK},
{GPAD_L3, K_BUTTON_LSTICK},
{GPAD_R3, K_BUTTON_RSTICK},
{GPAD_UP, K_DPAD_UP},
{GPAD_DOWN, K_DPAD_DOWN},
{GPAD_LEFT, K_DPAD_LEFT},
{GPAD_RIGHT, K_DPAD_RIGHT}
};
StickToCodeMap_t analogStickList[]
{
{GPAD_LY, GPAD_STICK_POS, K_DPAD_UP},
{GPAD_LY, GPAD_STICK_NEG, K_DPAD_DOWN},
{GPAD_LX, GPAD_STICK_POS, K_DPAD_RIGHT},
{GPAD_LX, GPAD_STICK_NEG, K_DPAD_LEFT},
};
keyNum_t menuScrollButtonList[]
{
K_DPAD_UP,
K_DPAD_DOWN,
K_DPAD_LEFT,
K_DPAD_RIGHT
};
constexpr auto VANILLA_KEY_NAME_COUNT = 95;
keyname_t extendedKeyNames[]
{
{"BUTTON_A", K_BUTTON_A},
{"BUTTON_B", K_BUTTON_B},
{"BUTTON_X", K_BUTTON_X},
{"BUTTON_Y", K_BUTTON_Y},
{"BUTTON_LSHLDR", K_BUTTON_LSHLDR},
{"BUTTON_RSHLDR", K_BUTTON_RSHLDR},
{"BUTTON_START", K_BUTTON_START},
{"BUTTON_BACK", K_BUTTON_BACK},
{"BUTTON_LSTICK", K_BUTTON_LSTICK},
{"BUTTON_RSTICK", K_BUTTON_RSTICK},
{"BUTTON_LTRIG", K_BUTTON_LTRIG},
{"BUTTON_RTRIG", K_BUTTON_RTRIG},
{"DPAD_UP", K_DPAD_UP},
{"DPAD_DOWN", K_DPAD_DOWN},
{"DPAD_LEFT", K_DPAD_LEFT},
{"DPAD_RIGHT", K_DPAD_RIGHT},
};
keyname_t combinedKeyNames[VANILLA_KEY_NAME_COUNT + std::extent_v<decltype(extendedKeyNames)> + 1];
GpadAxesGlob gaGlobs[MAX_GAMEPADS];
PlayerKeyState* playerKeys = reinterpret_cast<PlayerKeyState*>(0xA1B7D0);
keyname_t* vanillaKeyNames = reinterpret_cast<keyname_t*>(0x798580);
}
namespace Components
{
Gamepad::GamePad Gamepad::gamePads[1]{};
Gamepad::GamePad Gamepad::gamePads[Game::MAX_GAMEPADS]{};
Gamepad::GamePadGlobals Gamepad::gamePadGlobals[Game::MAX_GAMEPADS]{};
std::chrono::milliseconds Gamepad::timeAtFirstHeldMaxLookX = 0ms; // "For how much time in milliseconds has the player been holding a horizontal direction on their stick, fully" (-1.0 or 1.0)
bool Gamepad::isHoldingMaxLookX = false;
bool Gamepad::isADS;
@ -35,7 +102,7 @@ namespace Components
Dvar::Var Gamepad::xpadVerticalMultiplier;
Dvar::Var Gamepad::xpadAdsMultiplier;
Gamepad::GamePadStickDir Gamepad::lastMenuNavigationDirection = GPAD_STICK_DIR_COUNT;
Game::GamePadStickDir Gamepad::lastMenuNavigationDirection = Game::GPAD_STICK_DIR_COUNT;
std::chrono::milliseconds Gamepad::lastNavigationTime = 0ms;
std::chrono::milliseconds Gamepad::msBetweenNavigations = 220ms;
@ -285,27 +352,27 @@ namespace Components
std::chrono::milliseconds timeSinceLastNavigation = now - lastNavigationTime;
bool canNavigate = timeSinceLastNavigation > msBetweenNavigations;
if (gamePad.stickDown[1][GPAD_STICK_POS])
if (gamePad.stickDown[1][Game::GPAD_STICK_POS])
{
if (canNavigate)
{
Game::Menu_SetPrevCursorItem(Game::uiContext, menuDef, 1);
lastMenuNavigationDirection = GPAD_STICK_POS;
Menu_SetPrevCursorItem(Game::uiContext, menuDef, 1);
lastMenuNavigationDirection = Game::GPAD_STICK_POS;
lastNavigationTime = now;
}
}
else if (gamePad.stickDown[1][GPAD_STICK_NEG])
else if (gamePad.stickDown[1][Game::GPAD_STICK_NEG])
{
if (canNavigate)
{
Game::Menu_SetNextCursorItem(Game::uiContext, menuDef, 1);
lastMenuNavigationDirection = GPAD_STICK_NEG;
Menu_SetNextCursorItem(Game::uiContext, menuDef, 1);
lastMenuNavigationDirection = Game::GPAD_STICK_NEG;
lastNavigationTime = now;
}
}
else
{
lastMenuNavigationDirection = GPAD_STICK_DIR_COUNT;
lastMenuNavigationDirection = Game::GPAD_STICK_DIR_COUNT;
}
for (auto& mapping : menuMappings)
@ -360,7 +427,7 @@ namespace Components
void Gamepad::MouseOverride(Game::clientActive_t* clientActive, float* mx, float* my)
{
Gamepad::CL_GetMouseMovementCl(clientActive, mx, my);
CL_GetMouseMovementCl(clientActive, mx, my);
const auto& gamePad = gamePads[0];
@ -379,15 +446,15 @@ namespace Components
// Gamepad horizontal acceleration on view
if (abs(viewStickX) > 0.80f)
{
if (!Gamepad::isHoldingMaxLookX)
if (!isHoldingMaxLookX)
{
Gamepad::isHoldingMaxLookX = true;
Gamepad::timeAtFirstHeldMaxLookX = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
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()) -
Gamepad::timeAtFirstHeldMaxLookX;
timeAtFirstHeldMaxLookX;
#ifdef STEP_SENSITIVITY
if (hasBeenHoldingLeftXForMs < msBeforeUnlockingSensitivity) {
viewStickX *= lockedSensitivityMultiplier;
@ -400,8 +467,8 @@ namespace Components
}
else
{
Gamepad::isHoldingMaxLookX = false;
Gamepad::timeAtFirstHeldMaxLookX = 0ms;
isHoldingMaxLookX = false;
timeAtFirstHeldMaxLookX = 0ms;
viewStickX *= lockedSensitivityMultiplier;
}
@ -410,7 +477,7 @@ namespace Components
auto ps = &clientActive->snap.ps;
// DO NOT use clientActive->usingAds ! It only works for toggle ADS
if (Game::PM_IsAdsAllowed(ps) && Gamepad::isADS)
if (PM_IsAdsAllowed(ps) && isADS)
{
adsMultiplier = xpadAdsMultiplier.get<float>();
}
@ -478,6 +545,7 @@ namespace Components
bool Gamepad::GPad_Check(const int gamePadIndex, const int portIndex)
{
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePad = gamePads[gamePadIndex];
if (XInputGetCapabilities(portIndex, XINPUT_FLAG_GAMEPAD, &gamePad.caps) == ERROR_SUCCESS)
@ -495,13 +563,68 @@ namespace Components
{
auto currentGamePadNum = 0;
for (auto currentPort = 0; currentPort < XUSER_MAX_COUNT && currentGamePadNum < MAX_GAMEPADS; currentPort++)
for (auto currentPort = 0; currentPort < XUSER_MAX_COUNT && currentGamePadNum < Game::MAX_GAMEPADS; currentPort++)
{
if (GPad_Check(currentGamePadNum, currentPort))
currentGamePadNum++;
}
}
void Gamepad::CL_GamepadResetMenuScrollTime(const int gamePadIndex, const int key, const bool down, const unsigned time)
{
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePadGlobal = gamePadGlobals[gamePadIndex];
if (!down)
return;
const auto scrollDelayFirst = gpad_menu_scroll_delay_first.get<int>();
for(const auto scrollButton : Game::menuScrollButtonList)
{
if(key == scrollButton)
{
gamePadGlobal.nextScrollTime = scrollDelayFirst + time;
return;
}
}
}
void Gamepad::CL_GamepadEvent(int gamePadIndex, const Game::GamepadPhysicalAxis physicalAxis, const float value)
{
assert(gamePadIndex < Game::MAX_GAMEPADS);
assert(physicalAxis < Game::GPAD_PHYSAXIS_COUNT && physicalAxis >= 0);
Game::gaGlobs[gamePadIndex].axesValues[physicalAxis] = value;
}
void Gamepad::CL_GamepadButtonEvent(const int gamePadIndex, const int key, const Game::GamePadButtonEvent buttonEvent, unsigned time, Game::GamePadButton button)
{
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& keyState = Game::playerKeys[gamePadIndex];
keyState.keys[key].down = buttonEvent == Game::GPAD_BUTTON_PRESSED || buttonEvent == Game::GPAD_BUTTON_UPDATE;
if(buttonEvent == Game::GPAD_BUTTON_PRESSED)
{
if (++keyState.keys[key].repeats == 1)
keyState.anyKeyDown++;
}
else if(keyState.keys[key].repeats > 0)
{
keyState.keys[key].repeats = 0;
if (--keyState.anyKeyDown < 0)
keyState.anyKeyDown = 0;
}
}
void Gamepad::CL_GamepadButtonEventForPort(const int gamePadIndex, const int key, const Game::GamePadButtonEvent buttonEvent, const unsigned time, const Game::GamePadButton button)
{
if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_UI))
CL_GamepadResetMenuScrollTime(gamePadIndex, key, buttonEvent == Game::GPAD_BUTTON_PRESSED, time);
CL_GamepadButtonEvent(gamePadIndex, key, buttonEvent, time, button);
}
void Gamepad::GPad_ConvertStickToFloat(const short x, const short y, float& outX, float& outY)
{
Game::vec2_t stickVec;
@ -525,15 +648,121 @@ namespace Components
outY = stickVec[1] * len;
}
float Gamepad::GPad_GetStick(const int gamePadIndex, const Game::GamePadStick stick)
{
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePad = gamePads[gamePadIndex];
return gamePad.sticks[stick];
}
float Gamepad::GPad_GetButton(const int gamePadIndex, Game::GamePadButton button)
{
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePad = gamePads[gamePadIndex];
float value = 0.0f;
if(button & Game::GPAD_DIGITAL_MASK)
{
const auto buttonValue = button & Game::GPAD_VALUE_MASK;
value = buttonValue & gamePad.digitals ? 1.0f : 0.0f;
}
else if(button & Game::GPAD_ANALOG_MASK)
{
const auto analogIndex = button & Game::GPAD_VALUE_MASK;
if (analogIndex < std::extent_v<decltype(gamePad.analogs)>)
{
value = gamePad.analogs[analogIndex];
}
}
return value;
}
bool Gamepad::GPad_IsButtonPressed(const int gamePadIndex, Game::GamePadButton button)
{
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePad = gamePads[gamePadIndex];
bool down = false;
bool lastDown = false;
if(button & Game::GPAD_DIGITAL_MASK)
{
const auto buttonValue = button & Game::GPAD_VALUE_MASK;
if (button & 0xF && buttonValue & gamePad.digitals && (gamePad.digitals & 0xF) != (button & 0xF))
{
down = false;
lastDown = false;
}
else
{
down = (buttonValue & gamePad.digitals) != 0;
if (button & 0xF && buttonValue & gamePad.lastDigitals && (gamePad.lastDigitals & 0xF) != (button & 0xF))
lastDown = false;
else
lastDown = (buttonValue & gamePad.lastDigitals) != 0;
}
}
else if(button & Game::GPAD_ANALOG_MASK)
{
const auto analogIndex = button & Game::GPAD_VALUE_MASK;
assert(analogIndex < std::extent_v<decltype(gamePad.analogs)>);
if(analogIndex < std::extent_v<decltype(gamePad.analogs)>)
{
down = gamePad.analogs[analogIndex] > 0.0f;
lastDown = gamePad.lastAnalogs[analogIndex] > 0.0f;
}
}
return down && !lastDown;
}
bool Gamepad::GPad_ButtonRequiresUpdates(const int gamePadIndex, Game::GamePadButton button)
{
return button & Game::GPAD_ANALOG_MASK && GPad_GetButton(gamePadIndex, button) > 0.0f;
}
bool Gamepad::GPad_IsButtonReleased(int gamePadIndex, Game::GamePadButton button)
{
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePad = gamePads[gamePadIndex];
bool down = false;
bool lastDown = false;
if (button & Game::GPAD_DIGITAL_MASK)
{
const auto buttonValue = button & Game::GPAD_VALUE_MASK;
down = (gamePad.digitals & buttonValue) != 0;
lastDown = (gamePad.lastDigitals & buttonValue) != 0;
}
else if (button & Game::GPAD_ANALOG_MASK)
{
const auto analogIndex = button & Game::GPAD_VALUE_MASK;
assert(analogIndex < std::extent_v<decltype(gamePad.analogs)>);
if (analogIndex < std::extent_v<decltype(gamePad.analogs)>)
{
down = gamePad.analogs[analogIndex] > 0.0f;
lastDown = gamePad.lastAnalogs[analogIndex] > 0.0f;
}
}
return !down && lastDown;
}
void Gamepad::GPad_UpdateSticksDown(int gamePadIndex)
{
assert(gamePadIndex < MAX_GAMEPADS);
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePad = gamePads[gamePadIndex];
for (auto stickIndex = 0u; stickIndex < std::extent_v<decltype(GamePad::sticks)>; stickIndex++)
{
for (auto dir = 0; dir < GPAD_STICK_DIR_COUNT; dir++)
for (auto dir = 0; dir < Game::GPAD_STICK_DIR_COUNT; dir++)
{
gamePad.stickDownLast[stickIndex][dir] = gamePad.stickDown[stickIndex][dir];
@ -544,13 +773,13 @@ namespace Components
else
threshold += gpad_stick_pressed_hysteresis.get<float>();
if (dir == GPAD_STICK_POS)
if (dir == Game::GPAD_STICK_POS)
{
gamePad.stickDown[stickIndex][dir] = gamePad.sticks[stickIndex] > threshold;
}
else
{
assert(dir == GPAD_STICK_NEG);
assert(dir == Game::GPAD_STICK_NEG);
gamePad.stickDown[stickIndex][dir] = gamePad.sticks[stickIndex] < -threshold;
}
}
@ -559,7 +788,7 @@ namespace Components
void Gamepad::GPad_UpdateSticks(const int gamePadIndex, const XINPUT_GAMEPAD& state)
{
assert(gamePadIndex < MAX_GAMEPADS);
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePad = gamePads[gamePadIndex];
@ -583,17 +812,17 @@ namespace Components
{
Logger::Print("Left: X: %f Y: %f\n", lVec[0], lVec[1]);
Logger::Print("Right: X: %f Y: %f\n", rVec[0], rVec[1]);
Logger::Print("Down: %i:%i %i:%i %i:%i %i:%i\n", gamePad.stickDown[0][GPAD_STICK_POS], gamePad.stickDown[0][GPAD_STICK_NEG],
gamePad.stickDown[1][GPAD_STICK_POS], gamePad.stickDown[1][GPAD_STICK_NEG],
gamePad.stickDown[2][GPAD_STICK_POS], gamePad.stickDown[2][GPAD_STICK_NEG],
gamePad.stickDown[3][GPAD_STICK_POS], gamePad.stickDown[3][GPAD_STICK_NEG]);
Logger::Print("Down: %i:%i %i:%i %i:%i %i:%i\n", gamePad.stickDown[0][Game::GPAD_STICK_POS], gamePad.stickDown[0][Game::GPAD_STICK_NEG],
gamePad.stickDown[1][Game::GPAD_STICK_POS], gamePad.stickDown[1][Game::GPAD_STICK_NEG],
gamePad.stickDown[2][Game::GPAD_STICK_POS], gamePad.stickDown[2][Game::GPAD_STICK_NEG],
gamePad.stickDown[3][Game::GPAD_STICK_POS], gamePad.stickDown[3][Game::GPAD_STICK_NEG]);
}
#endif
}
void Gamepad::GPad_UpdateDigitals(const int gamePadIndex, const XINPUT_GAMEPAD& state)
{
assert(gamePadIndex < MAX_GAMEPADS);
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePad = gamePads[gamePadIndex];
@ -617,7 +846,7 @@ namespace Components
void Gamepad::GPad_UpdateAnalogs(const int gamePadIndex, const XINPUT_GAMEPAD& state)
{
assert(gamePadIndex < MAX_GAMEPADS);
assert(gamePadIndex < Game::MAX_GAMEPADS);
auto& gamePad = gamePads[gamePadIndex];
@ -646,7 +875,7 @@ namespace Components
{
GPad_RefreshAll();
for (auto currentGamePadIndex = 0; currentGamePadIndex < MAX_GAMEPADS; currentGamePadIndex++)
for (auto currentGamePadIndex = 0; currentGamePadIndex < Game::MAX_GAMEPADS; currentGamePadIndex++)
{
const auto& gamePad = gamePads[currentGamePadIndex];
if (!gamePad.enabled)
@ -665,6 +894,64 @@ namespace Components
void Gamepad::IN_GamePadsMove()
{
GPad_UpdateAll();
const auto time = Game::Sys_Milliseconds();
bool gpadPresent = false;
for(auto gamePadIndex = 0; gamePadIndex < Game::MAX_GAMEPADS; gamePadIndex++)
{
const auto& gamePad = gamePads[gamePadIndex];
if(gamePad.enabled)
{
gpadPresent = true;
const auto lx = GPad_GetStick(gamePadIndex, Game::GPAD_LX);
const auto ly = GPad_GetStick(gamePadIndex, Game::GPAD_LY);
const auto rx = GPad_GetStick(gamePadIndex, Game::GPAD_RX);
const auto ry = GPad_GetStick(gamePadIndex, Game::GPAD_RY);
const auto leftTrig = GPad_GetButton(gamePadIndex, Game::GPAD_L_TRIG);
const auto rightTrig = GPad_GetButton(gamePadIndex, Game::GPAD_R_TRIG);
CL_GamepadEvent(gamePadIndex, Game::GPAD_PHYSAXIS_LSTICK_X, lx);
CL_GamepadEvent(gamePadIndex, Game::GPAD_PHYSAXIS_LSTICK_Y, ly);
CL_GamepadEvent(gamePadIndex, Game::GPAD_PHYSAXIS_RSTICK_X, rx);
CL_GamepadEvent(gamePadIndex, Game::GPAD_PHYSAXIS_RSTICK_Y, ry);
CL_GamepadEvent(gamePadIndex, Game::GPAD_PHYSAXIS_LTRIGGER, leftTrig);
CL_GamepadEvent(gamePadIndex, Game::GPAD_PHYSAXIS_RTRIGGER, rightTrig);
for (const auto& buttonMapping : Game::buttonList)
{
if(GPad_IsButtonPressed(gamePadIndex, buttonMapping.padButton))
{
CL_GamepadButtonEventForPort(
gamePadIndex,
buttonMapping.code,
Game::GPAD_BUTTON_PRESSED,
time,
buttonMapping.padButton);
}
else if(GPad_ButtonRequiresUpdates(gamePadIndex, buttonMapping.padButton))
{
CL_GamepadButtonEventForPort(
gamePadIndex,
buttonMapping.code,
Game::GPAD_BUTTON_UPDATE,
time,
buttonMapping.padButton);
}
else if(GPad_IsButtonReleased(gamePadIndex, buttonMapping.padButton))
{
CL_GamepadButtonEventForPort(
gamePadIndex,
buttonMapping.code,
Game::GPAD_BUTTON_RELEASED,
time,
buttonMapping.padButton);
}
}
}
}
gpad_present.setRaw(gpadPresent);
}
@ -705,24 +992,37 @@ namespace Components
InitDvars();
}
void Gamepad::CreateKeyNameMap()
{
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)>);
Game::combinedKeyNames[std::extent_v<decltype(Game::combinedKeyNames)> - 1] = { nullptr, 0 };
Utils::Hook::Set<Game::keyname_t*>(0x4A780A, Game::combinedKeyNames);
Utils::Hook::Set<Game::keyname_t*>(0x4A7810, Game::combinedKeyNames);
Utils::Hook::Set<Game::keyname_t*>(0x435C9F, Game::combinedKeyNames);
}
Gamepad::Gamepad()
{
if (ZoneBuilder::IsEnabled())
return;
// use the xinput state when creating a usercmd
Utils::Hook(0x5A6DB9, Gamepad::CL_CreateCmdStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x5A6DB9, CL_CreateCmdStub, HOOK_JUMP).install()->quick();
// package the forward and right move components in the move buttons
Utils::Hook(0x60E38D, Gamepad::MSG_WriteDeltaUsercmdKeyStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x60E38D, MSG_WriteDeltaUsercmdKeyStub, HOOK_JUMP).install()->quick();
// send two bytes for sending movement data
Utils::Hook::Set<BYTE>(0x60E501, 16);
Utils::Hook::Set<BYTE>(0x60E5CD, 16);
// make sure to parse the movement data properly and apply it
Utils::Hook(0x492127, Gamepad::MSG_ReadDeltaUsercmdKeyStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x492009, Gamepad::MSG_ReadDeltaUsercmdKeyStub2, HOOK_JUMP).install()->quick();
Utils::Hook(0x492127, MSG_ReadDeltaUsercmdKeyStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x492009, MSG_ReadDeltaUsercmdKeyStub2, HOOK_JUMP).install()->quick();
CreateKeyNameMap();
if (Dedicated::IsEnabled())
return;

View File

@ -1,23 +1,115 @@
#pragma once
namespace Game
{
static constexpr auto MAX_GAMEPADS = 1;
static constexpr auto GPAD_VALUE_MASK = 0xFFFFFFFu;
static constexpr auto GPAD_DIGITAL_MASK = 1u << 28;
static constexpr auto GPAD_ANALOG_MASK = 1u << 29;
static constexpr auto GPAD_STICK_MASK = 1u << 30;
enum GamePadButton
{
GPAD_NONE = 0,
GPAD_UP = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_DPAD_UP & GPAD_VALUE_MASK),
GPAD_DOWN = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_DPAD_DOWN & GPAD_VALUE_MASK),
GPAD_LEFT = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_DPAD_LEFT & GPAD_VALUE_MASK),
GPAD_RIGHT = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_DPAD_RIGHT & GPAD_VALUE_MASK),
GPAD_START = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_START & GPAD_VALUE_MASK),
GPAD_BACK = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_BACK & GPAD_VALUE_MASK),
GPAD_L3 = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_LEFT_THUMB & GPAD_VALUE_MASK),
GPAD_R3 = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_RIGHT_THUMB & GPAD_VALUE_MASK),
GPAD_L_SHLDR = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_LEFT_SHOULDER & GPAD_VALUE_MASK),
GPAD_R_SHLDR = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_RIGHT_SHOULDER & GPAD_VALUE_MASK),
GPAD_A = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_A & GPAD_VALUE_MASK),
GPAD_B = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_B & GPAD_VALUE_MASK),
GPAD_X = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_X & GPAD_VALUE_MASK),
GPAD_Y = GPAD_DIGITAL_MASK | (XINPUT_GAMEPAD_Y & GPAD_VALUE_MASK),
GPAD_L_TRIG = GPAD_ANALOG_MASK | (0 & GPAD_VALUE_MASK),
GPAD_R_TRIG = GPAD_ANALOG_MASK | (1 & GPAD_VALUE_MASK),
};
enum GamePadStick
{
GPAD_INVALID = 0x0,
GPAD_LX = GPAD_STICK_MASK | (0 & GPAD_VALUE_MASK),
GPAD_LY = GPAD_STICK_MASK | (1 & GPAD_VALUE_MASK),
GPAD_RX = GPAD_STICK_MASK | (2 & GPAD_VALUE_MASK),
GPAD_RY = GPAD_STICK_MASK | (3 & GPAD_VALUE_MASK),
};
enum GamePadButtonEvent
{
GPAD_BUTTON_RELEASED = 0x0,
GPAD_BUTTON_PRESSED = 0x1,
GPAD_BUTTON_UPDATE = 0x2,
};
enum GamepadPhysicalAxis
{
GPAD_PHYSAXIS_NONE = -1,
GPAD_PHYSAXIS_RSTICK_X = 0x0,
GPAD_PHYSAXIS_RSTICK_Y = 0x1,
GPAD_PHYSAXIS_LSTICK_X = 0x2,
GPAD_PHYSAXIS_LSTICK_Y = 0x3,
GPAD_PHYSAXIS_RTRIGGER = 0x4,
GPAD_PHYSAXIS_LTRIGGER = 0x5,
GPAD_PHYSAXIS_COUNT,
};
enum GamePadStickDir
{
GPAD_STICK_POS = 0x0,
GPAD_STICK_NEG = 0x1,
GPAD_STICK_DIR_COUNT
};
enum GamepadMapping
{
GPAD_MAP_NONE = -1,
GPAD_MAP_LINEAR = 0x0,
GPAD_MAP_SQUARED = 0x1,
GPAD_MAP_COUNT = 0x2
};
struct ButtonToCodeMap_t
{
GamePadButton padButton;
int code;
};
struct StickToCodeMap_t
{
GamePadStick padStick;
GamePadStickDir padStickDir;
int code;
};
struct GamepadVirtualAxisMapping
{
GamepadPhysicalAxis physicalAxis;
GamepadMapping mapType;
};
struct GpadAxesGlob
{
float axesValues[GPAD_PHYSAXIS_COUNT];
GamepadVirtualAxisMapping virtualAxes[GPAD_PHYSAXIS_COUNT];
};
}
namespace Components
{
class Gamepad : public Component
{
static constexpr auto MAX_GAMEPADS = 1;
static constexpr float TRIGGER_THRESHOLD_F = static_cast<float>(XINPUT_GAMEPAD_TRIGGER_THRESHOLD) / static_cast<float>(0xFF);
public:
Gamepad();
enum GamePadStickDir
{
GPAD_STICK_POS = 0x0,
GPAD_STICK_NEG = 0x1,
GPAD_STICK_DIR_COUNT
};
struct GamePad
{
bool enabled;
@ -28,8 +120,8 @@ namespace Components
float lastAnalogs[2];
float sticks[4];
float lastSticks[4];
bool stickDown[4][GPAD_STICK_DIR_COUNT];
bool stickDownLast[4][GPAD_STICK_DIR_COUNT];
bool stickDown[4][Game::GPAD_STICK_DIR_COUNT];
bool stickDownLast[4][Game::GPAD_STICK_DIR_COUNT];
float lowRumble;
float highRumble;
@ -37,6 +129,11 @@ namespace Components
XINPUT_CAPABILITIES caps;
};
struct GamePadGlobals
{
unsigned nextScrollTime;
};
struct ActionMapping
{
int input;
@ -68,7 +165,8 @@ namespace Components
};
private:
static GamePad gamePads[MAX_GAMEPADS];
static GamePad gamePads[Game::MAX_GAMEPADS];
static GamePadGlobals gamePadGlobals[Game::MAX_GAMEPADS];
static bool isHoldingMaxLookX;
static std::chrono::milliseconds timeAtFirstHeldMaxLookX;
@ -76,7 +174,7 @@ namespace Components
static std::chrono::milliseconds lastNavigationTime;
static std::chrono::milliseconds msBetweenNavigations;
static GamePadStickDir lastMenuNavigationDirection;
static Game::GamePadStickDir lastMenuNavigationDirection;
static Dvar::Var gpad_enabled;
static Dvar::Var gpad_debug;
@ -125,7 +223,17 @@ namespace Components
static void GetRightStick01Value(XINPUT_STATE* xiState, float& x, float& y);
static void GamepadStickTo01(SHORT value, SHORT deadzone, float& output01);
static void CL_GamepadResetMenuScrollTime(int gamePadIndex, int key, bool down, unsigned int time);
static void CL_GamepadEvent(int gamePadIndex, Game::GamepadPhysicalAxis physicalAxis, float value);
static void CL_GamepadButtonEvent(int gamePadIndex, int key, Game::GamePadButtonEvent buttonEvent, unsigned time, Game::GamePadButton button);
static void CL_GamepadButtonEventForPort(int gamePadIndex, int key, Game::GamePadButtonEvent buttonEvent, unsigned int time, Game::GamePadButton button);
static void GPad_ConvertStickToFloat(short x, short y, float& outX, float& outY);
static float GPad_GetStick(int gamePadIndex, Game::GamePadStick stick);
static float GPad_GetButton(int gamePadIndex, Game::GamePadButton button);
static bool GPad_IsButtonPressed(int gamePadIndex, Game::GamePadButton button);
static bool GPad_ButtonRequiresUpdates(int gamePadIndex, Game::GamePadButton button);
static bool GPad_IsButtonReleased(int gamePadIndex, Game::GamePadButton button);
static void GPad_UpdateSticksDown(int gamePadIndex);
static void GPad_UpdateSticks(int gamePadIndex, const XINPUT_GAMEPAD& state);
@ -140,5 +248,7 @@ namespace Components
static void InitDvars();
static void IN_Init_Hk();
static void CreateKeyNameMap();
};
}

View File

@ -206,11 +206,48 @@ namespace Game
};
#pragma pack(pop)
enum KeyCatch_t
{
KEYCATCH_CONSOLE = 0x1,
KEYCATCH_UNKNOWN2 = 0x2,
KEYCATCH_UNKNOWN4 = 0x4,
KEYCATCH_LOCATION_SELECTION = 0x8,
KEYCATCH_UI = 0x10,
KEYCATCH_CHAT = 0x20,
KEYCATCH_UNKNOWN40 = 0x40,
KEYCATCH_UNKNOWN80 = 0x80,
KEYCATCH_UNKNOWN100 = 0x100,
};
enum keyNum_t
{
K_NONE = 0x0,
K_FIRSTGAMEPADBUTTON_RANGE_1 = 0x1, // First Gamepad 1
K_BUTTON_A = 0x1,
K_BUTTON_B = 0x2,
K_BUTTON_X = 0x3,
K_BUTTON_Y = 0x4,
K_BUTTON_LSHLDR = 0x5,
K_BUTTON_RSHLDR = 0x6,
K_LASTGAMEPADBUTTON_RANGE_1 = 0x6, // Last Gamepad 1
K_TAB = 0x9,
K_ENTER = 0xD,
K_FIRSTGAMEPADBUTTON_RANGE_2 = 0xE, // First Gamepad 2
K_BUTTON_START = 0xE,
K_BUTTON_BACK = 0xF,
K_BUTTON_LSTICK = 0x10,
K_BUTTON_RSTICK = 0x11,
K_BUTTON_LTRIG = 0x12,
K_BUTTON_RTRIG = 0x13,
K_FIRSTDPAD = 0x14, // First Dpad
K_DPAD_UP = 0x14,
K_DPAD_DOWN = 0x15,
K_DPAD_LEFT = 0x16,
K_DPAD_RIGHT = 0x17,
K_LASTDPAD = 0x17, // Last Dpad
K_DPAD_LEFTRIGHT = 0x18,
K_DPAD_UPDOWN = 0x19,
K_LASTGAMEPADBUTTON_RANGE_2 = 0x19, // Last Gamepad 2
K_ESCAPE = 0x1B,
K_SPACE = 0x20,
K_BACKSPACE = 0x7F,
@ -1104,6 +1141,40 @@ namespace Game
LOC_SEL_INPUT_CANCEL = 0x2,
};
struct field_t
{
int cursor;
int scroll;
int drawWidth;
int widthInPixels;
float charHeight;
int fixedSize;
char buffer[256];
};
struct KeyState
{
int down;
int repeats;
const char* binding;
};
struct PlayerKeyState
{
field_t chatField;
int chat_team;
int overstrikeMode;
int anyKeyDown;
KeyState keys[256];
LocSelInputState locSelInputState;
};
struct keyname_t
{
const char* name;
int keynum;
};
struct clSnapshot_t
{
playerState_s ps;