Add binding commands to keys for controllers
This commit is contained in:
parent
2decfa2c45
commit
6d598df56d
@ -109,6 +109,7 @@ namespace Components
|
||||
Game::Dvar_SetCommand(this->dvar->name, Utils::String::VA("%f", value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Dvar::Var::setRaw(int integer)
|
||||
{
|
||||
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user