From 29d1ed934fa2bce8ec0c270e51e6e40d4c63f657 Mon Sep 17 00:00:00 2001 From: John Cronin Date: Thu, 18 Jan 2018 17:55:10 +0000 Subject: [PATCH] Add autofire capability --- Windows/Gopher/ConfigFile.cpp | 6 ++ Windows/Gopher/Gopher.cpp | 102 ++++++++++++++++++++++++++++------ Windows/Gopher/Gopher.h | 24 +++++++- 3 files changed, 113 insertions(+), 19 deletions(-) diff --git a/Windows/Gopher/ConfigFile.cpp b/Windows/Gopher/ConfigFile.cpp index 4ef4cc9..f29711a 100644 --- a/Windows/Gopher/ConfigFile.cpp +++ b/Windows/Gopher/ConfigFile.cpp @@ -117,6 +117,12 @@ void ConfigFile::ExtractKeys() outfile << "GAMEPAD_TRIGGER_LEFT = 0" << std::endl; outfile << "GAMEPAD_TRIGGER_RIGHT = 0" << std::endl; outfile << "\n" << std::endl; + outfile << "# SET TO 1 FOR EACH CONTROLLER BUTTON (AS NAMED ABOVE) TO HAVE Gopher360 CONTINUALLY PULSE THE KEY WHILST IT IS HELD DOWN (I.E. AUTOFIRE)" << std::endl; + outfile << "GAMEPAD_DPAD_UP_REPEAT = 1" << std::endl; + outfile << "GAMEPAD_DPAD_DOWN_REPEAT = 1" << std::endl; + outfile << "GAMEPAD_DPAD_LEFT_REPEAT = 1" << std::endl; + outfile << "GAMEPAD_DPAD_RIGHT_REPEAT = 1" << std::endl; + outfile << "\n" << std::endl; outfile << "# ALLOWED CURSOR SPEEDS, FIRST WILL BE CHOSEN BY DEFAULT. VALUES > 1.0 WILL BE IGNORED. NO SPACES." << std::endl; outfile << "CURSOR_SPEED = ULTRALOW=0.005,LOW=0.015,MED=0.025,HIGH=0.04" << std::endl; outfile << "# SET ACCELERATION FACTOR FOR NON-LINEAR CURSOR SPEED" << std::endl; diff --git a/Windows/Gopher/Gopher.cpp b/Windows/Gopher/Gopher.cpp index 0a10464..81ea948 100644 --- a/Windows/Gopher/Gopher.cpp +++ b/Windows/Gopher/Gopher.cpp @@ -69,6 +69,24 @@ void Gopher::loadConfigFile() GAMEPAD_TRIGGER_LEFT = strtol(cfg.getValueOfKey("GAMEPAD_TRIGGER_LEFT").c_str(), 0, 0); GAMEPAD_TRIGGER_RIGHT = strtol(cfg.getValueOfKey("GAMEPAD_TRIGGER_RIGHT").c_str(), 0, 0); + //Whether to enable the automatic repeat (autofire) functionality for each button + GAMEPAD_DPAD_UP_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_DPAD_UP_REPEAT").c_str(), 0, 0); + GAMEPAD_DPAD_DOWN_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_DPAD_DOWN_REPEAT").c_str(), 0, 0); + GAMEPAD_DPAD_LEFT_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_DPAD_LEFT_REPEAT").c_str(), 0, 0); + GAMEPAD_DPAD_RIGHT_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_DPAD_RIGHT_REPEAT").c_str(), 0, 0); + GAMEPAD_START_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_START_REPEAT").c_str(), 0, 0); + GAMEPAD_BACK_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_BACK_REPEAT").c_str(), 0, 0); + GAMEPAD_LEFT_THUMB_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_LEFT_THUMB_REPEAT").c_str(), 0, 0); + GAMEPAD_RIGHT_THUMB_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_RIGHT_THUMB_REPEAT").c_str(), 0, 0); + GAMEPAD_LEFT_SHOULDER_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_LEFT_SHOULDER_REPEAT").c_str(), 0, 0); + GAMEPAD_RIGHT_SHOULDER_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_RIGHT_SHOULDER_REPEAT").c_str(), 0, 0); + GAMEPAD_A_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_A_REPEAT").c_str(), 0, 0); + GAMEPAD_B_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_B_REPEAT").c_str(), 0, 0); + GAMEPAD_X_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_X_REPEAT").c_str(), 0, 0); + GAMEPAD_Y_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_Y_REPEAT").c_str(), 0, 0); + GAMEPAD_TRIGGER_LEFT_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_TRIGGER_LEFT_REPEAT").c_str(), 0, 0); + GAMEPAD_TRIGGER_RIGHT_REPEAT = strtol(cfg.getValueOfKey("GAMEPAD_TRIGGER_RIGHT_REPEAT").c_str(), 0, 0); + // Acceleration factor acceleration_factor = strtof(cfg.getValueOfKey("ACCELERATION_FACTOR").c_str(), 0); @@ -175,33 +193,33 @@ void Gopher::loop() { //Set all controller keys. handleTriggers(GAMEPAD_TRIGGER_LEFT, GAMEPAD_TRIGGER_RIGHT); if (GAMEPAD_DPAD_UP) - mapKeyboard(XINPUT_GAMEPAD_DPAD_UP, GAMEPAD_DPAD_UP); + mapKeyboard(XINPUT_GAMEPAD_DPAD_UP, GAMEPAD_DPAD_UP, GAMEPAD_DPAD_UP_REPEAT); if (GAMEPAD_DPAD_DOWN) - mapKeyboard(XINPUT_GAMEPAD_DPAD_DOWN, GAMEPAD_DPAD_DOWN); + mapKeyboard(XINPUT_GAMEPAD_DPAD_DOWN, GAMEPAD_DPAD_DOWN, GAMEPAD_DPAD_DOWN_REPEAT); if (GAMEPAD_DPAD_LEFT) - mapKeyboard(XINPUT_GAMEPAD_DPAD_LEFT, GAMEPAD_DPAD_LEFT); + mapKeyboard(XINPUT_GAMEPAD_DPAD_LEFT, GAMEPAD_DPAD_LEFT, GAMEPAD_DPAD_LEFT_REPEAT); if (GAMEPAD_DPAD_RIGHT) - mapKeyboard(XINPUT_GAMEPAD_DPAD_RIGHT, GAMEPAD_DPAD_RIGHT); + mapKeyboard(XINPUT_GAMEPAD_DPAD_RIGHT, GAMEPAD_DPAD_RIGHT, GAMEPAD_DPAD_RIGHT_REPEAT); if (GAMEPAD_START) - mapKeyboard(XINPUT_GAMEPAD_START, GAMEPAD_START); + mapKeyboard(XINPUT_GAMEPAD_START, GAMEPAD_START, GAMEPAD_START_REPEAT); if (GAMEPAD_BACK) - mapKeyboard(XINPUT_GAMEPAD_BACK, GAMEPAD_BACK); + mapKeyboard(XINPUT_GAMEPAD_BACK, GAMEPAD_BACK, GAMEPAD_BACK_REPEAT); if (GAMEPAD_LEFT_THUMB) - mapKeyboard(XINPUT_GAMEPAD_LEFT_THUMB, GAMEPAD_LEFT_THUMB); + mapKeyboard(XINPUT_GAMEPAD_LEFT_THUMB, GAMEPAD_LEFT_THUMB, GAMEPAD_LEFT_THUMB_REPEAT); if (GAMEPAD_RIGHT_THUMB) - mapKeyboard(XINPUT_GAMEPAD_RIGHT_THUMB, GAMEPAD_RIGHT_THUMB); + mapKeyboard(XINPUT_GAMEPAD_RIGHT_THUMB, GAMEPAD_RIGHT_THUMB, GAMEPAD_RIGHT_THUMB_REPEAT); if (GAMEPAD_LEFT_SHOULDER) - mapKeyboard(XINPUT_GAMEPAD_LEFT_SHOULDER, GAMEPAD_LEFT_SHOULDER); + mapKeyboard(XINPUT_GAMEPAD_LEFT_SHOULDER, GAMEPAD_LEFT_SHOULDER, GAMEPAD_LEFT_SHOULDER_REPEAT); if (GAMEPAD_RIGHT_SHOULDER) - mapKeyboard(XINPUT_GAMEPAD_RIGHT_SHOULDER, GAMEPAD_RIGHT_SHOULDER); + mapKeyboard(XINPUT_GAMEPAD_RIGHT_SHOULDER, GAMEPAD_RIGHT_SHOULDER, GAMEPAD_RIGHT_SHOULDER_REPEAT); if (GAMEPAD_A) - mapKeyboard(XINPUT_GAMEPAD_A, GAMEPAD_A); + mapKeyboard(XINPUT_GAMEPAD_A, GAMEPAD_A, GAMEPAD_A_REPEAT); if (GAMEPAD_B) - mapKeyboard(XINPUT_GAMEPAD_B, GAMEPAD_B); + mapKeyboard(XINPUT_GAMEPAD_B, GAMEPAD_B, GAMEPAD_B_REPEAT); if (GAMEPAD_X) - mapKeyboard(XINPUT_GAMEPAD_X, GAMEPAD_X); + mapKeyboard(XINPUT_GAMEPAD_X, GAMEPAD_X, GAMEPAD_X_REPEAT); if (GAMEPAD_Y) - mapKeyboard(XINPUT_GAMEPAD_Y, GAMEPAD_Y); + mapKeyboard(XINPUT_GAMEPAD_Y, GAMEPAD_Y, GAMEPAD_Y_REPEAT); } void Gopher::pulseVibrate(const int duration, const int l, const int r) const @@ -343,10 +361,27 @@ void Gopher::handleTriggers(WORD lKey, WORD rKey) if (lTriggerIsDown) { inputKeyboardDown(lKey); + _lTriggerLongPressCount = 0; } else { inputKeyboardUp(lKey); + _lTriggerLongPressMax = 500; // reset long press max trigger + } + } + else if (GAMEPAD_TRIGGER_LEFT_REPEAT && lTriggerIsDown) + { + _lTriggerLongPressCount++; + if (_lTriggerLongPressCount * SLEEP_AMOUNT > _lTriggerLongPressMax) + { + // pulse the key + inputKeyboardUp(lKey); + inputKeyboardDown(lKey); + _lTriggerLongPressCount = 0; + if (_lTriggerLongPressMax == 500) + _lTriggerLongPressMax = 200; + else + _lTriggerLongPressMax = 70; } } @@ -360,6 +395,22 @@ void Gopher::handleTriggers(WORD lKey, WORD rKey) else { inputKeyboardUp(rKey); + _rTriggerLongPressMax = 500; + } + } + else if (GAMEPAD_TRIGGER_RIGHT_REPEAT && rTriggerIsDown) + { + _rTriggerLongPressCount++; + if (_rTriggerLongPressCount * SLEEP_AMOUNT > _rTriggerLongPressMax) + { + // pulse the key + inputKeyboardUp(rKey); + inputKeyboardDown(rKey); + _rTriggerLongPressCount = 0; + if (_rTriggerLongPressMax == 500) + _rTriggerLongPressMax = 200; + else + _rTriggerLongPressMax = 70; } } } @@ -368,6 +419,7 @@ void Gopher::setXboxClickState(DWORD STATE) { _xboxClickIsDown[STATE] = false; _xboxClickIsUp[STATE] = false; + _xboxClickIsDownLong[STATE] = false; if (!this->xboxClickStateExists(STATE)) { @@ -381,21 +433,28 @@ void Gopher::setXboxClickState(DWORD STATE) _xboxClickStateLastIteration[STATE] = true; _xboxClickIsDown[STATE] = true; _xboxClickDownLength[STATE] = 0; - _xboxClickIsDownLong[STATE] = false; + _xboxClickDownLongMax[STATE] = 500; } if (isDown && _xboxClickStateLastIteration[STATE]) { + // _xboxClickDownLong toggles every 200 ms of button depression _xboxClickDownLength[STATE] = _xboxClickDownLength[STATE] + 1; - if (_xboxClickDownLength[STATE] * SLEEP_AMOUNT > 200) + if (_xboxClickDownLength[STATE] * SLEEP_AMOUNT > _xboxClickDownLongMax[STATE]) + { _xboxClickIsDownLong[STATE] = true; + _xboxClickDownLength[STATE] = 0; + if (_xboxClickDownLongMax[STATE] == 500) + _xboxClickDownLongMax[STATE] = 200; + else + _xboxClickDownLongMax[STATE] = 70; + } } if (!isDown && _xboxClickStateLastIteration[STATE]) { _xboxClickStateLastIteration[STATE] = false; _xboxClickIsUp[STATE] = true; - _xboxClickIsDownLong[STATE] = false; } _xboxClickStateLastIteration[STATE] = isDown; @@ -412,7 +471,7 @@ bool Gopher::xboxClickStateExists(DWORD xinput) return true; } -void Gopher::mapKeyboard(DWORD STATE, WORD key) +void Gopher::mapKeyboard(DWORD STATE, WORD key, int repeat) { setXboxClickState(STATE); if (_xboxClickIsDown[STATE]) @@ -424,6 +483,13 @@ void Gopher::mapKeyboard(DWORD STATE, WORD key) { inputKeyboardUp(key); } + + if (repeat && _xboxClickIsDownLong[STATE]) + { + // pulse key off and on + inputKeyboardUp(key); + inputKeyboardDown(key); + } } void Gopher::mapMouseClick(DWORD STATE, DWORD keyDown, DWORD keyUp) diff --git a/Windows/Gopher/Gopher.h b/Windows/Gopher/Gopher.h index b2cf6fa..465f95d 100644 --- a/Windows/Gopher/Gopher.h +++ b/Windows/Gopher/Gopher.h @@ -39,6 +39,10 @@ class Gopher bool _hidden = false; //press Y to hide, check this var bool _lTriggerPrevious = false; bool _rTriggerPrevious = false; + int _lTriggerLongPressCount = 0; + int _rTriggerLongPressCount = 0; + int _lTriggerLongPressMax = 500; // number of milliseconds until next pulsing of the key - automatically decreased with each press + int _rTriggerLongPressMax = 500; std::vector speeds; // contains actual speeds to choose std::vector speed_names; // contains pretty names of speeds to display @@ -73,11 +77,29 @@ class Gopher DWORD GAMEPAD_TRIGGER_LEFT = NULL; DWORD GAMEPAD_TRIGGER_RIGHT = NULL; + // Key repeats (autofire) + int GAMEPAD_DPAD_UP_REPEAT = 0; + int GAMEPAD_DPAD_DOWN_REPEAT = 0; + int GAMEPAD_DPAD_LEFT_REPEAT = 0; + int GAMEPAD_DPAD_RIGHT_REPEAT = 0; + int GAMEPAD_START_REPEAT = 0; + int GAMEPAD_BACK_REPEAT = 0; + int GAMEPAD_LEFT_THUMB_REPEAT = 0; + int GAMEPAD_RIGHT_THUMB_REPEAT = 0; + int GAMEPAD_LEFT_SHOULDER_REPEAT = 0; + int GAMEPAD_RIGHT_SHOULDER_REPEAT = 0; + int GAMEPAD_A_REPEAT = 0; + int GAMEPAD_B_REPEAT = 0; + int GAMEPAD_X_REPEAT = 0; + int GAMEPAD_Y_REPEAT = 0; + int GAMEPAD_TRIGGER_LEFT_REPEAT = 0; + int GAMEPAD_TRIGGER_RIGHT_REPEAT = 0; std::map _xboxClickStateLastIteration; std::map _xboxClickIsDown; std::map _xboxClickIsDownLong; std::map _xboxClickDownLength; + std::map _xboxClickDownLongMax; std::map _xboxClickIsUp; CXBOXController* _controller; @@ -112,7 +134,7 @@ class Gopher bool xboxClickStateExists(DWORD xinput); - void mapKeyboard(DWORD STATE, WORD key); + void mapKeyboard(DWORD STATE, WORD key, int repeat); void mapMouseClick(DWORD STATE, DWORD keyDown, DWORD keyUp);