Write gamepad axis configuration to config file
This commit is contained in:
parent
dcbb120de1
commit
8cd99235c0
@ -45,6 +45,32 @@ namespace Game
|
|||||||
GPAD_INVALID
|
GPAD_INVALID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char* physicalAxisNames[GPAD_PHYSAXIS_COUNT]
|
||||||
|
{
|
||||||
|
"A_RSTICK_X",
|
||||||
|
"A_RSTICK_Y",
|
||||||
|
"A_LSTICK_X",
|
||||||
|
"A_LSTICK_Y",
|
||||||
|
"A_RTRIGGER",
|
||||||
|
"A_LTRIGGER"
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* virtualAxisNames[GPAD_VIRTAXIS_COUNT]
|
||||||
|
{
|
||||||
|
"VA_SIDE",
|
||||||
|
"VA_FORWARD",
|
||||||
|
"VA_UP",
|
||||||
|
"VA_YAW",
|
||||||
|
"VA_PITCH",
|
||||||
|
"VA_ATTACK"
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* gamePadMappingTypeNames[GPAD_MAP_COUNT]
|
||||||
|
{
|
||||||
|
"MAP_LINEAR",
|
||||||
|
"MAP_SQUARED"
|
||||||
|
};
|
||||||
|
|
||||||
keyNum_t menuScrollButtonList[]
|
keyNum_t menuScrollButtonList[]
|
||||||
{
|
{
|
||||||
K_APAD_UP,
|
K_APAD_UP,
|
||||||
@ -80,7 +106,6 @@ namespace Game
|
|||||||
|
|
||||||
keyname_t combinedKeyNames[VANILLA_KEY_NAME_COUNT + std::extent_v<decltype(extendedKeyNames)> + 1];
|
keyname_t combinedKeyNames[VANILLA_KEY_NAME_COUNT + std::extent_v<decltype(extendedKeyNames)> + 1];
|
||||||
|
|
||||||
GpadAxesGlob gaGlobs[MAX_GAMEPADS];
|
|
||||||
PlayerKeyState* playerKeys = reinterpret_cast<PlayerKeyState*>(0xA1B7D0);
|
PlayerKeyState* playerKeys = reinterpret_cast<PlayerKeyState*>(0xA1B7D0);
|
||||||
keyname_t* vanillaKeyNames = reinterpret_cast<keyname_t*>(0x798580);
|
keyname_t* vanillaKeyNames = reinterpret_cast<keyname_t*>(0x798580);
|
||||||
}
|
}
|
||||||
@ -88,7 +113,8 @@ namespace Game
|
|||||||
namespace Components
|
namespace Components
|
||||||
{
|
{
|
||||||
Gamepad::GamePad Gamepad::gamePads[Game::MAX_GAMEPADS]{};
|
Gamepad::GamePad Gamepad::gamePads[Game::MAX_GAMEPADS]{};
|
||||||
Gamepad::GamePadGlobals Gamepad::gamePadGlobals[Game::MAX_GAMEPADS]{};
|
Gamepad::GamePadGlobals Gamepad::gamePadGlobals[Game::MAX_GAMEPADS]{{}};
|
||||||
|
int Gamepad::gamePadBindingsModifiedFlags = 0;
|
||||||
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)
|
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::isHoldingMaxLookX = false;
|
||||||
bool Gamepad::isADS;
|
bool Gamepad::isADS;
|
||||||
@ -161,6 +187,18 @@ namespace Components
|
|||||||
Gamepad::ActionMapping(XINPUT_GAMEPAD_DPAD_UP, "actionslot 4"),
|
Gamepad::ActionMapping(XINPUT_GAMEPAD_DPAD_UP, "actionslot 4"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Gamepad::GamePadGlobals::GamePadGlobals()
|
||||||
|
: axes{},
|
||||||
|
nextScrollTime(0)
|
||||||
|
{
|
||||||
|
for (auto& virtualAxis : axes.virtualAxes)
|
||||||
|
{
|
||||||
|
virtualAxis.physicalAxis = Game::GPAD_PHYSAXIS_NONE;
|
||||||
|
virtualAxis.mapType = Game::GPAD_MAP_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Same thing
|
// Same thing
|
||||||
|
|
||||||
// void Gamepad::Vibrate(int leftVal, int rightVal)
|
// void Gamepad::Vibrate(int leftVal, int rightVal)
|
||||||
@ -549,9 +587,9 @@ namespace Components
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const auto scrollDelayFirst = gpad_menu_scroll_delay_first.get<int>();
|
const auto scrollDelayFirst = gpad_menu_scroll_delay_first.get<int>();
|
||||||
for(const auto scrollButton : Game::menuScrollButtonList)
|
for (const auto scrollButton : Game::menuScrollButtonList)
|
||||||
{
|
{
|
||||||
if(key == scrollButton)
|
if (key == scrollButton)
|
||||||
{
|
{
|
||||||
gamePadGlobal.nextScrollTime = scrollDelayFirst + time;
|
gamePadGlobal.nextScrollTime = scrollDelayFirst + time;
|
||||||
return;
|
return;
|
||||||
@ -568,46 +606,48 @@ namespace Components
|
|||||||
|
|
||||||
const auto stick = Game::stickForAxis[physicalAxis];
|
const auto stick = Game::stickForAxis[physicalAxis];
|
||||||
const auto stickIndex = stick & Game::GPAD_VALUE_MASK;
|
const auto stickIndex = stick & Game::GPAD_VALUE_MASK;
|
||||||
if(stick != Game::GPAD_INVALID)
|
if (stick != Game::GPAD_INVALID)
|
||||||
{
|
{
|
||||||
assert(stickIndex < 4);
|
assert(stickIndex < 4);
|
||||||
const auto& mapping = Game::analogStickList[stickIndex];
|
const auto& mapping = Game::analogStickList[stickIndex];
|
||||||
|
|
||||||
if(gamePad.stickDown[stickIndex][Game::GPAD_STICK_POS])
|
if (gamePad.stickDown[stickIndex][Game::GPAD_STICK_POS])
|
||||||
{
|
{
|
||||||
const Game::GamePadButtonEvent event = gamePad.stickDownLast[stickIndex][Game::GPAD_STICK_POS] ? Game::GPAD_BUTTON_UPDATE : Game::GPAD_BUTTON_PRESSED;
|
const Game::GamePadButtonEvent event = gamePad.stickDownLast[stickIndex][Game::GPAD_STICK_POS] ? Game::GPAD_BUTTON_UPDATE : Game::GPAD_BUTTON_PRESSED;
|
||||||
CL_GamepadButtonEvent(gamePadIndex, mapping.posCode, event, time, Game::GPAD_NONE);
|
CL_GamepadButtonEvent(gamePadIndex, mapping.posCode, event, time, Game::GPAD_NONE);
|
||||||
}
|
}
|
||||||
else if(gamePad.stickDown[stickIndex][Game::GPAD_STICK_NEG])
|
else if (gamePad.stickDown[stickIndex][Game::GPAD_STICK_NEG])
|
||||||
{
|
{
|
||||||
const Game::GamePadButtonEvent event = gamePad.stickDownLast[stickIndex][Game::GPAD_STICK_NEG] ? Game::GPAD_BUTTON_UPDATE : Game::GPAD_BUTTON_PRESSED;
|
const Game::GamePadButtonEvent event = gamePad.stickDownLast[stickIndex][Game::GPAD_STICK_NEG] ? Game::GPAD_BUTTON_UPDATE : Game::GPAD_BUTTON_PRESSED;
|
||||||
CL_GamepadButtonEvent(gamePadIndex, mapping.negCode, event, time, Game::GPAD_NONE);
|
CL_GamepadButtonEvent(gamePadIndex, mapping.negCode, event, time, Game::GPAD_NONE);
|
||||||
}
|
}
|
||||||
else if(gamePad.stickDownLast[stickIndex][Game::GPAD_STICK_POS])
|
else if (gamePad.stickDownLast[stickIndex][Game::GPAD_STICK_POS])
|
||||||
{
|
{
|
||||||
CL_GamepadButtonEvent(gamePadIndex, mapping.posCode, Game::GPAD_BUTTON_RELEASED, time, Game::GPAD_NONE);
|
CL_GamepadButtonEvent(gamePadIndex, mapping.posCode, Game::GPAD_BUTTON_RELEASED, time, Game::GPAD_NONE);
|
||||||
}
|
}
|
||||||
else if(gamePad.stickDownLast[stickIndex][Game::GPAD_STICK_NEG])
|
else if (gamePad.stickDownLast[stickIndex][Game::GPAD_STICK_NEG])
|
||||||
{
|
{
|
||||||
CL_GamepadButtonEvent(gamePadIndex, mapping.negCode, Game::GPAD_BUTTON_RELEASED, time, Game::GPAD_NONE);
|
CL_GamepadButtonEvent(gamePadIndex, mapping.negCode, Game::GPAD_BUTTON_RELEASED, time, Game::GPAD_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gamepad::CL_GamepadEvent(int gamePadIndex, const Game::GamepadPhysicalAxis physicalAxis, const float value, const unsigned time)
|
void Gamepad::CL_GamepadEvent(const int gamePadIndex, const Game::GamepadPhysicalAxis physicalAxis, const float value, const unsigned time)
|
||||||
{
|
{
|
||||||
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
||||||
assert(physicalAxis < Game::GPAD_PHYSAXIS_COUNT && physicalAxis >= 0);
|
assert(physicalAxis < Game::GPAD_PHYSAXIS_COUNT && physicalAxis >= 0);
|
||||||
|
|
||||||
Game::gaGlobs[gamePadIndex].axesValues[physicalAxis] = value;
|
auto& gamePadGlobal = gamePadGlobals[gamePadIndex];
|
||||||
|
|
||||||
|
gamePadGlobal.axes.axesValues[physicalAxis] = value;
|
||||||
CL_GamepadGenerateAPad(gamePadIndex, physicalAxis, time);
|
CL_GamepadGenerateAPad(gamePadIndex, physicalAxis, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gamepad::UI_GamepadKeyEvent(const int gamePadIndex, const int key, const bool down)
|
void Gamepad::UI_GamepadKeyEvent(const int gamePadIndex, const int key, const bool down)
|
||||||
{
|
{
|
||||||
for(const auto& mapping : controllerMenuKeyMappings)
|
for (const auto& mapping : controllerMenuKeyMappings)
|
||||||
{
|
{
|
||||||
if(mapping.controllerKey == key)
|
if (mapping.controllerKey == key)
|
||||||
{
|
{
|
||||||
Game::UI_KeyEvent(gamePadIndex, mapping.pcKey, down);
|
Game::UI_KeyEvent(gamePadIndex, mapping.pcKey, down);
|
||||||
return;
|
return;
|
||||||
@ -623,22 +663,22 @@ namespace Components
|
|||||||
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
||||||
auto& gamePadGlobal = gamePadGlobals[gamePadIndex];
|
auto& gamePadGlobal = gamePadGlobals[gamePadIndex];
|
||||||
|
|
||||||
if(Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_UI))
|
if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_UI))
|
||||||
{
|
{
|
||||||
const int scrollDelayFirst = gpad_menu_scroll_delay_first.get<int>();
|
const int scrollDelayFirst = gpad_menu_scroll_delay_first.get<int>();
|
||||||
const int scrollDelayRest = gpad_menu_scroll_delay_rest.get<int>();
|
const int scrollDelayRest = gpad_menu_scroll_delay_rest.get<int>();
|
||||||
|
|
||||||
for(const auto menuScrollButton : Game::menuScrollButtonList)
|
for (const auto menuScrollButton : Game::menuScrollButtonList)
|
||||||
{
|
{
|
||||||
if(key == menuScrollButton)
|
if (key == menuScrollButton)
|
||||||
{
|
{
|
||||||
if(repeatCount == 1)
|
if (repeatCount == 1)
|
||||||
{
|
{
|
||||||
gamePadGlobal.nextScrollTime = time + scrollDelayFirst;
|
gamePadGlobal.nextScrollTime = time + scrollDelayFirst;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(time > gamePadGlobal.nextScrollTime)
|
if (time > gamePadGlobal.nextScrollTime)
|
||||||
{
|
{
|
||||||
gamePadGlobal.nextScrollTime = time + scrollDelayRest;
|
gamePadGlobal.nextScrollTime = time + scrollDelayRest;
|
||||||
return false;
|
return false;
|
||||||
@ -661,12 +701,12 @@ namespace Components
|
|||||||
auto& keyState = Game::playerKeys[gamePadIndex];
|
auto& keyState = Game::playerKeys[gamePadIndex];
|
||||||
keyState.keys[key].down = pressedOrUpdated;
|
keyState.keys[key].down = pressedOrUpdated;
|
||||||
|
|
||||||
if(pressedOrUpdated)
|
if (pressedOrUpdated)
|
||||||
{
|
{
|
||||||
if (++keyState.keys[key].repeats == 1)
|
if (++keyState.keys[key].repeats == 1)
|
||||||
keyState.anyKeyDown++;
|
keyState.anyKeyDown++;
|
||||||
}
|
}
|
||||||
else if(buttonEvent == Game::GPAD_BUTTON_RELEASED && keyState.keys[key].repeats > 0)
|
else if (buttonEvent == Game::GPAD_BUTTON_RELEASED && keyState.keys[key].repeats > 0)
|
||||||
{
|
{
|
||||||
keyState.keys[key].repeats = 0;
|
keyState.keys[key].repeats = 0;
|
||||||
if (--keyState.anyKeyDown < 0)
|
if (--keyState.anyKeyDown < 0)
|
||||||
@ -676,13 +716,13 @@ namespace Components
|
|||||||
if (pressedOrUpdated && CL_CheckForIgnoreDueToRepeat(gamePadIndex, key, keyState.keys[key].repeats, time))
|
if (pressedOrUpdated && CL_CheckForIgnoreDueToRepeat(gamePadIndex, key, keyState.keys[key].repeats, time))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_LOCATION_SELECTION) && pressedOrUpdated)
|
if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_LOCATION_SELECTION) && pressedOrUpdated)
|
||||||
{
|
{
|
||||||
if(key == Game::K_BUTTON_B || keyState.keys[key].binding && strcmp(keyState.keys[key].binding, "+actionslot 4") == 0)
|
if (key == Game::K_BUTTON_B || keyState.keys[key].binding && strcmp(keyState.keys[key].binding, "+actionslot 4") == 0)
|
||||||
{
|
{
|
||||||
keyState.locSelInputState = Game::LOC_SEL_INPUT_CANCEL;
|
keyState.locSelInputState = Game::LOC_SEL_INPUT_CANCEL;
|
||||||
}
|
}
|
||||||
else if(key == Game::K_BUTTON_A || keyState.keys[key].binding && strcmp(keyState.keys[key].binding, "+attack") == 0)
|
else if (key == Game::K_BUTTON_A || keyState.keys[key].binding && strcmp(keyState.keys[key].binding, "+attack") == 0)
|
||||||
{
|
{
|
||||||
keyState.locSelInputState = Game::LOC_SEL_INPUT_CONFIRM;
|
keyState.locSelInputState = Game::LOC_SEL_INPUT_CONFIRM;
|
||||||
}
|
}
|
||||||
@ -694,7 +734,7 @@ namespace Components
|
|||||||
const auto* keyBinding = keyState.keys[key].binding;
|
const auto* keyBinding = keyState.keys[key].binding;
|
||||||
|
|
||||||
char cmd[1024];
|
char cmd[1024];
|
||||||
if(pressedOrUpdated)
|
if (pressedOrUpdated)
|
||||||
{
|
{
|
||||||
if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_UI))
|
if (Game::Key_IsKeyCatcherActive(gamePadIndex, Game::KEYCATCH_UI))
|
||||||
{
|
{
|
||||||
@ -789,12 +829,12 @@ namespace Components
|
|||||||
|
|
||||||
float value = 0.0f;
|
float value = 0.0f;
|
||||||
|
|
||||||
if(button & Game::GPAD_DIGITAL_MASK)
|
if (button & Game::GPAD_DIGITAL_MASK)
|
||||||
{
|
{
|
||||||
const auto buttonValue = button & Game::GPAD_VALUE_MASK;
|
const auto buttonValue = button & Game::GPAD_VALUE_MASK;
|
||||||
value = buttonValue & gamePad.digitals ? 1.0f : 0.0f;
|
value = buttonValue & gamePad.digitals ? 1.0f : 0.0f;
|
||||||
}
|
}
|
||||||
else if(button & Game::GPAD_ANALOG_MASK)
|
else if (button & Game::GPAD_ANALOG_MASK)
|
||||||
{
|
{
|
||||||
const auto analogIndex = button & Game::GPAD_VALUE_MASK;
|
const auto analogIndex = button & Game::GPAD_VALUE_MASK;
|
||||||
if (analogIndex < std::extent_v<decltype(gamePad.analogs)>)
|
if (analogIndex < std::extent_v<decltype(gamePad.analogs)>)
|
||||||
@ -814,18 +854,18 @@ namespace Components
|
|||||||
bool down = false;
|
bool down = false;
|
||||||
bool lastDown = false;
|
bool lastDown = false;
|
||||||
|
|
||||||
if(button & Game::GPAD_DIGITAL_MASK)
|
if (button & Game::GPAD_DIGITAL_MASK)
|
||||||
{
|
{
|
||||||
const auto buttonValue = button & Game::GPAD_VALUE_MASK;
|
const auto buttonValue = button & Game::GPAD_VALUE_MASK;
|
||||||
down = (buttonValue & gamePad.digitals) != 0;
|
down = (buttonValue & gamePad.digitals) != 0;
|
||||||
lastDown = (buttonValue & gamePad.lastDigitals) != 0;
|
lastDown = (buttonValue & gamePad.lastDigitals) != 0;
|
||||||
}
|
}
|
||||||
else if(button & Game::GPAD_ANALOG_MASK)
|
else if (button & Game::GPAD_ANALOG_MASK)
|
||||||
{
|
{
|
||||||
const auto analogIndex = button & Game::GPAD_VALUE_MASK;
|
const auto analogIndex = button & Game::GPAD_VALUE_MASK;
|
||||||
assert(analogIndex < std::extent_v<decltype(gamePad.analogs)>);
|
assert(analogIndex < std::extent_v<decltype(gamePad.analogs)>);
|
||||||
|
|
||||||
if(analogIndex < std::extent_v<decltype(gamePad.analogs)>)
|
if (analogIndex < std::extent_v<decltype(gamePad.analogs)>)
|
||||||
{
|
{
|
||||||
down = gamePad.analogs[analogIndex] > 0.0f;
|
down = gamePad.analogs[analogIndex] > 0.0f;
|
||||||
lastDown = gamePad.lastAnalogs[analogIndex] > 0.0f;
|
lastDown = gamePad.lastAnalogs[analogIndex] > 0.0f;
|
||||||
@ -870,7 +910,7 @@ namespace Components
|
|||||||
return !down && lastDown;
|
return !down && lastDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gamepad::GPad_UpdateSticksDown(int gamePadIndex)
|
void Gamepad::GPad_UpdateSticksDown(const int gamePadIndex)
|
||||||
{
|
{
|
||||||
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
||||||
auto& gamePad = gamePads[gamePadIndex];
|
auto& gamePad = gamePads[gamePadIndex];
|
||||||
@ -1012,11 +1052,11 @@ namespace Components
|
|||||||
const auto time = Game::Sys_Milliseconds();
|
const auto time = Game::Sys_Milliseconds();
|
||||||
|
|
||||||
bool gpadPresent = false;
|
bool gpadPresent = false;
|
||||||
for(auto gamePadIndex = 0; gamePadIndex < Game::MAX_GAMEPADS; gamePadIndex++)
|
for (auto gamePadIndex = 0; gamePadIndex < Game::MAX_GAMEPADS; gamePadIndex++)
|
||||||
{
|
{
|
||||||
const auto& gamePad = gamePads[gamePadIndex];
|
const auto& gamePad = gamePads[gamePadIndex];
|
||||||
|
|
||||||
if(gamePad.enabled)
|
if (gamePad.enabled)
|
||||||
{
|
{
|
||||||
gpadPresent = true;
|
gpadPresent = true;
|
||||||
const auto lx = GPad_GetStick(gamePadIndex, Game::GPAD_LX);
|
const auto lx = GPad_GetStick(gamePadIndex, Game::GPAD_LX);
|
||||||
@ -1035,7 +1075,7 @@ namespace Components
|
|||||||
|
|
||||||
for (const auto& buttonMapping : Game::buttonList)
|
for (const auto& buttonMapping : Game::buttonList)
|
||||||
{
|
{
|
||||||
if(GPad_IsButtonPressed(gamePadIndex, buttonMapping.padButton))
|
if (GPad_IsButtonPressed(gamePadIndex, buttonMapping.padButton))
|
||||||
{
|
{
|
||||||
CL_GamepadButtonEventForPort(
|
CL_GamepadButtonEventForPort(
|
||||||
gamePadIndex,
|
gamePadIndex,
|
||||||
@ -1044,7 +1084,7 @@ namespace Components
|
|||||||
time,
|
time,
|
||||||
buttonMapping.padButton);
|
buttonMapping.padButton);
|
||||||
}
|
}
|
||||||
else if(GPad_ButtonRequiresUpdates(gamePadIndex, buttonMapping.padButton))
|
else if (GPad_ButtonRequiresUpdates(gamePadIndex, buttonMapping.padButton))
|
||||||
{
|
{
|
||||||
CL_GamepadButtonEventForPort(
|
CL_GamepadButtonEventForPort(
|
||||||
gamePadIndex,
|
gamePadIndex,
|
||||||
@ -1053,7 +1093,7 @@ namespace Components
|
|||||||
time,
|
time,
|
||||||
buttonMapping.padButton);
|
buttonMapping.padButton);
|
||||||
}
|
}
|
||||||
else if(GPad_IsButtonReleased(gamePadIndex, buttonMapping.padButton))
|
else if (GPad_IsButtonReleased(gamePadIndex, buttonMapping.padButton))
|
||||||
{
|
{
|
||||||
CL_GamepadButtonEventForPort(
|
CL_GamepadButtonEventForPort(
|
||||||
gamePadIndex,
|
gamePadIndex,
|
||||||
@ -1078,6 +1118,153 @@ namespace Components
|
|||||||
IN_GamePadsMove();
|
IN_GamePadsMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Gamepad::Gamepad_WriteBindings(const int gamePadIndex, const int handle)
|
||||||
|
{
|
||||||
|
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
||||||
|
auto& gamePadGlobal = gamePadGlobals[gamePadIndex];
|
||||||
|
|
||||||
|
Game::FS_Printf(handle, "unbindallaxis\n");
|
||||||
|
|
||||||
|
for(auto virtualAxisIndex = 0u; virtualAxisIndex < Game::GPAD_VIRTAXIS_COUNT; virtualAxisIndex++)
|
||||||
|
{
|
||||||
|
const auto& axisMapping = gamePadGlobal.axes.virtualAxes[virtualAxisIndex];
|
||||||
|
if (axisMapping.physicalAxis <= Game::GPAD_PHYSAXIS_NONE || axisMapping.physicalAxis >= Game::GPAD_PHYSAXIS_COUNT
|
||||||
|
|| axisMapping.mapType <= Game::GPAD_MAP_NONE || axisMapping.mapType >= Game::GPAD_MAP_COUNT)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* physicalAxisName = Game::physicalAxisNames[axisMapping.physicalAxis];
|
||||||
|
const auto* virtualAxisName = Game::virtualAxisNames[virtualAxisIndex];
|
||||||
|
const auto* mappingName = Game::gamePadMappingTypeNames[axisMapping.mapType];
|
||||||
|
|
||||||
|
Game::FS_Printf(handle, "bindaxis %s %s %s\n", physicalAxisName, virtualAxisName, mappingName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gamepad::Key_WriteBindings_Hk(const int localClientNum, const int handle)
|
||||||
|
{
|
||||||
|
// Call original function
|
||||||
|
Utils::Hook::Call<void(int, int)>(0x4A5A20)(localClientNum, handle);
|
||||||
|
|
||||||
|
Gamepad_WriteBindings(0, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void __declspec(naked) Gamepad::Com_WriteConfiguration_Modified_Stub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov eax, [ecx + 0x18]
|
||||||
|
or eax, gamePadBindingsModifiedFlags // Also check for gamePadBindingsModifiedFlags
|
||||||
|
test al, 1
|
||||||
|
jz endMethod
|
||||||
|
mov gamePadBindingsModifiedFlags, 0 // Reset gamePadBindingsModifiedFlags
|
||||||
|
mov eax, [ecx + 0x18] // Restore eax to dvar_modified_flags
|
||||||
|
|
||||||
|
push 0x60B26E
|
||||||
|
retn
|
||||||
|
|
||||||
|
endMethod:
|
||||||
|
push 0x60B298
|
||||||
|
retn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Gamepad::Gamepad_BindAxis(const int gamePadIndex, const Game::GamepadPhysicalAxis realIndex, const Game::GamepadVirtualAxis axisIndex, const Game::GamepadMapping mapType)
|
||||||
|
{
|
||||||
|
assert(gamePadIndex < Game::MAX_GAMEPADS);
|
||||||
|
assert(realIndex > Game::GPAD_PHYSAXIS_NONE && realIndex < Game::GPAD_PHYSAXIS_COUNT);
|
||||||
|
assert(axisIndex > Game::GPAD_VIRTAXIS_NONE && axisIndex < Game::GPAD_VIRTAXIS_COUNT);
|
||||||
|
assert(mapType > Game::GPAD_MAP_NONE && mapType < Game::GPAD_MAP_COUNT);
|
||||||
|
|
||||||
|
auto& gamePadGlobal = gamePadGlobals[gamePadIndex];
|
||||||
|
gamePadGlobal.axes.virtualAxes[axisIndex].physicalAxis = realIndex;
|
||||||
|
gamePadGlobal.axes.virtualAxes[axisIndex].mapType = mapType;
|
||||||
|
|
||||||
|
gamePadBindingsModifiedFlags |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::GamepadPhysicalAxis Gamepad::StringToPhysicalAxis(const char* str)
|
||||||
|
{
|
||||||
|
for (auto i = 0u; i < std::extent_v<decltype(Game::physicalAxisNames)>; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(str, Game::physicalAxisNames[i]) == 0)
|
||||||
|
return static_cast<Game::GamepadPhysicalAxis>(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Game::GPAD_PHYSAXIS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::GamepadVirtualAxis Gamepad::StringToVirtualAxis(const char* str)
|
||||||
|
{
|
||||||
|
for (auto i = 0u; i < std::extent_v<decltype(Game::virtualAxisNames)>; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(str, Game::virtualAxisNames[i]) == 0)
|
||||||
|
return static_cast<Game::GamepadVirtualAxis>(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Game::GPAD_VIRTAXIS_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::GamepadMapping Gamepad::StringToGamePadMapping(const char* str)
|
||||||
|
{
|
||||||
|
for (auto i = 0u; i < std::extent_v<decltype(Game::gamePadMappingTypeNames)>; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(str, Game::gamePadMappingTypeNames[i]) == 0)
|
||||||
|
return static_cast<Game::GamepadMapping>(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Game::GPAD_MAP_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gamepad::Axis_Bind_f(Command::Params* params)
|
||||||
|
{
|
||||||
|
if (params->length() < 4)
|
||||||
|
{
|
||||||
|
Logger::Print("bindaxis <real axis> <virtual axis> <input type>\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* physicalAxisText = params->get(1);
|
||||||
|
const auto* virtualAxisText = params->get(2);
|
||||||
|
const auto* mappingText = params->get(3);
|
||||||
|
|
||||||
|
const Game::GamepadPhysicalAxis physicalAxis = StringToPhysicalAxis(physicalAxisText);
|
||||||
|
if (physicalAxis == Game::GPAD_PHYSAXIS_NONE)
|
||||||
|
{
|
||||||
|
Logger::Print("\"%s\" isn't a valid physical axis\n", physicalAxisText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Game::GamepadVirtualAxis virtualAxis = StringToVirtualAxis(virtualAxisText);
|
||||||
|
if (virtualAxis == Game::GPAD_VIRTAXIS_NONE)
|
||||||
|
{
|
||||||
|
Logger::Print("\"%s\" isn't a valid virtual axis\n", virtualAxisText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Game::GamepadMapping mapping = StringToGamePadMapping(mappingText);
|
||||||
|
if (mapping == Game::GPAD_MAP_NONE)
|
||||||
|
{
|
||||||
|
Logger::Print("\"%s\" isn't a valid input type\n", mappingText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gamepad_BindAxis(0, physicalAxis, virtualAxis, mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gamepad::Axis_Unbindall_f(Command::Params* params)
|
||||||
|
{
|
||||||
|
auto& gamePadGlobal = gamePadGlobals[0];
|
||||||
|
|
||||||
|
for (auto& virtualAxis : gamePadGlobal.axes.virtualAxes)
|
||||||
|
{
|
||||||
|
virtualAxis.physicalAxis = Game::GPAD_PHYSAXIS_NONE;
|
||||||
|
virtualAxis.mapType = Game::GPAD_MAP_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Gamepad::InitDvars()
|
void Gamepad::InitDvars()
|
||||||
{
|
{
|
||||||
gpad_enabled = Dvar::Register<bool>("gpad_enabled", false, Game::DVAR_FLAG_SAVED, "Game pad enabled");
|
gpad_enabled = Dvar::Register<bool>("gpad_enabled", false, Game::DVAR_FLAG_SAVED, "Game pad enabled");
|
||||||
@ -1111,7 +1298,7 @@ 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};
|
||||||
|
|
||||||
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);
|
||||||
@ -1137,8 +1324,16 @@ namespace Components
|
|||||||
Utils::Hook(0x492127, MSG_ReadDeltaUsercmdKeyStub, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x492127, MSG_ReadDeltaUsercmdKeyStub, HOOK_JUMP).install()->quick();
|
||||||
Utils::Hook(0x492009, MSG_ReadDeltaUsercmdKeyStub2, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x492009, MSG_ReadDeltaUsercmdKeyStub2, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
|
// Also rewrite configuration when gamepad config is dirty
|
||||||
|
Utils::Hook(0x60B264, Com_WriteConfiguration_Modified_Stub, HOOK_JUMP).install()->quick();
|
||||||
|
|
||||||
|
Utils::Hook(0x60B223, Key_WriteBindings_Hk, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
CreateKeyNameMap();
|
CreateKeyNameMap();
|
||||||
|
|
||||||
|
Command::Add("bindaxis", Axis_Bind_f);
|
||||||
|
Command::Add("unbindallaxis", Axis_Unbindall_f);
|
||||||
|
|
||||||
if (Dedicated::IsEnabled())
|
if (Dedicated::IsEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -60,6 +60,19 @@ namespace Game
|
|||||||
GPAD_PHYSAXIS_COUNT,
|
GPAD_PHYSAXIS_COUNT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum GamepadVirtualAxis
|
||||||
|
{
|
||||||
|
GPAD_VIRTAXIS_NONE = -1,
|
||||||
|
GPAD_VIRTAXIS_SIDE = 0x0,
|
||||||
|
GPAD_VIRTAXIS_FORWARD = 0x1,
|
||||||
|
GPAD_VIRTAXIS_UP = 0x2,
|
||||||
|
GPAD_VIRTAXIS_YAW = 0x3,
|
||||||
|
GPAD_VIRTAXIS_PITCH = 0x4,
|
||||||
|
GPAD_VIRTAXIS_ATTACK = 0x5,
|
||||||
|
|
||||||
|
GPAD_VIRTAXIS_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
enum GamePadStickDir
|
enum GamePadStickDir
|
||||||
{
|
{
|
||||||
GPAD_STICK_POS = 0x0,
|
GPAD_STICK_POS = 0x0,
|
||||||
@ -73,7 +86,8 @@ namespace Game
|
|||||||
GPAD_MAP_NONE = -1,
|
GPAD_MAP_NONE = -1,
|
||||||
GPAD_MAP_LINEAR = 0x0,
|
GPAD_MAP_LINEAR = 0x0,
|
||||||
GPAD_MAP_SQUARED = 0x1,
|
GPAD_MAP_SQUARED = 0x1,
|
||||||
GPAD_MAP_COUNT = 0x2
|
|
||||||
|
GPAD_MAP_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ButtonToCodeMap_t
|
struct ButtonToCodeMap_t
|
||||||
@ -98,7 +112,7 @@ namespace Game
|
|||||||
struct GpadAxesGlob
|
struct GpadAxesGlob
|
||||||
{
|
{
|
||||||
float axesValues[GPAD_PHYSAXIS_COUNT];
|
float axesValues[GPAD_PHYSAXIS_COUNT];
|
||||||
GamepadVirtualAxisMapping virtualAxes[GPAD_PHYSAXIS_COUNT];
|
GamepadVirtualAxisMapping virtualAxes[GPAD_VIRTAXIS_COUNT];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +146,10 @@ namespace Components
|
|||||||
|
|
||||||
struct GamePadGlobals
|
struct GamePadGlobals
|
||||||
{
|
{
|
||||||
|
Game::GpadAxesGlob axes;
|
||||||
unsigned nextScrollTime;
|
unsigned nextScrollTime;
|
||||||
|
|
||||||
|
GamePadGlobals();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ActionMapping
|
struct ActionMapping
|
||||||
@ -156,6 +173,8 @@ namespace Components
|
|||||||
static GamePad gamePads[Game::MAX_GAMEPADS];
|
static GamePad gamePads[Game::MAX_GAMEPADS];
|
||||||
static GamePadGlobals gamePadGlobals[Game::MAX_GAMEPADS];
|
static GamePadGlobals gamePadGlobals[Game::MAX_GAMEPADS];
|
||||||
|
|
||||||
|
static int gamePadBindingsModifiedFlags;
|
||||||
|
|
||||||
static bool isHoldingMaxLookX;
|
static bool isHoldingMaxLookX;
|
||||||
static std::chrono::milliseconds timeAtFirstHeldMaxLookX;
|
static std::chrono::milliseconds timeAtFirstHeldMaxLookX;
|
||||||
static bool isADS;
|
static bool isADS;
|
||||||
@ -236,6 +255,17 @@ namespace Components
|
|||||||
static void IN_GamePadsMove();
|
static void IN_GamePadsMove();
|
||||||
static void IN_Frame_Hk();
|
static void IN_Frame_Hk();
|
||||||
|
|
||||||
|
static void Gamepad_WriteBindings(int gamePadIndex, int handle);
|
||||||
|
static void Key_WriteBindings_Hk(int localClientNum, int handle);
|
||||||
|
static void Com_WriteConfiguration_Modified_Stub();
|
||||||
|
|
||||||
|
static void Gamepad_BindAxis(int gamePadIndex, Game::GamepadPhysicalAxis realIndex, Game::GamepadVirtualAxis axisIndex, Game::GamepadMapping mapType);
|
||||||
|
static Game::GamepadPhysicalAxis StringToPhysicalAxis(const char* str);
|
||||||
|
static Game::GamepadVirtualAxis StringToVirtualAxis(const char* str);
|
||||||
|
static Game::GamepadMapping StringToGamePadMapping(const char* str);
|
||||||
|
static void Axis_Bind_f(Command::Params* params);
|
||||||
|
static void Axis_Unbindall_f(Command::Params* params);
|
||||||
|
|
||||||
static void InitDvars();
|
static void InitDvars();
|
||||||
static void IN_Init_Hk();
|
static void IN_Init_Hk();
|
||||||
|
|
||||||
|
@ -130,6 +130,7 @@ namespace Game
|
|||||||
FS_FCloseFile_t FS_FCloseFile = FS_FCloseFile_t(0x462000);
|
FS_FCloseFile_t FS_FCloseFile = FS_FCloseFile_t(0x462000);
|
||||||
FS_WriteFile_t FS_WriteFile = FS_WriteFile_t(0x426450);
|
FS_WriteFile_t FS_WriteFile = FS_WriteFile_t(0x426450);
|
||||||
FS_Write_t FS_Write = FS_Write_t(0x4C06E0);
|
FS_Write_t FS_Write = FS_Write_t(0x4C06E0);
|
||||||
|
FS_Printf_t FS_Printf = FS_Printf_t(0x459320);
|
||||||
FS_Read_t FS_Read = FS_Read_t(0x4A04C0);
|
FS_Read_t FS_Read = FS_Read_t(0x4A04C0);
|
||||||
FS_Seek_t FS_Seek = FS_Seek_t(0x4A63D0);
|
FS_Seek_t FS_Seek = FS_Seek_t(0x4A63D0);
|
||||||
FS_FTell_t FS_FTell = FS_FTell_t(0x4E6760);
|
FS_FTell_t FS_FTell = FS_FTell_t(0x4E6760);
|
||||||
|
@ -302,6 +302,9 @@ namespace Game
|
|||||||
typedef int(__cdecl * FS_Write_t)(const void* buffer, size_t size, int file);
|
typedef int(__cdecl * FS_Write_t)(const void* buffer, size_t size, int file);
|
||||||
extern FS_Write_t FS_Write;
|
extern FS_Write_t FS_Write;
|
||||||
|
|
||||||
|
typedef int(__cdecl * FS_Printf_t)(int file, const char* fmt, ...);
|
||||||
|
extern FS_Printf_t FS_Printf;
|
||||||
|
|
||||||
typedef int(__cdecl * FS_Read_t)(void* buffer, size_t size, int file);
|
typedef int(__cdecl * FS_Read_t)(void* buffer, size_t size, int file);
|
||||||
extern FS_Read_t FS_Read;
|
extern FS_Read_t FS_Read;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user