This commit is contained in:
bluechilliz3 2026-05-31 16:46:06 +00:00 committed by GitHub
commit 5833e32a2c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 147 additions and 0 deletions

View file

@ -10,6 +10,18 @@
#define TRANSLATE_INPUT(S, X) SDL_GameControllerGetButton(controller, S) << FirstBitLow(X)
#define VIBRATION_TIMEOUT_MS 5000
static bool IsBoostOnRightTriggerActive()
{
// true if sonic is werehog and right trigger preference is boost
return !App::s_isWerehog && Config::RightTriggerAction == ERightTriggerAction::Boost;
}
static uint32_t GetBoostCancelDurationMs()
{
int32_t fps = Config::FPS > 0 ? Config::FPS : 60;
return static_cast<uint32_t>(2000 / fps);
}
class Controller
{
public:
@ -20,6 +32,13 @@ public:
XAMINPUT_VIBRATION vibration{ 0, 0 };
int index{};
// for when user sets Config::RightTriggerAction to ERightTriggerAction this
// increases stability to allow square/X to be recognised by the game while
// right trigger is being pressed down especially when the user is moving
// the thumbsticks
bool xWasHeldLastPoll{};
uint32_t xCancelUntilTick{};
Controller() = default;
explicit Controller(int index) : Controller(SDL_GameControllerOpen(index))
@ -99,6 +118,33 @@ public:
pad.bLeftTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) >> 7;
pad.bRightTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7;
if (IsBoostOnRightTriggerActive())
{
bool xHeldPhysically = SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_X) != 0;
bool xRisingEdge = xHeldPhysically && !xWasHeldLastPoll;
bool rtPulled = pad.bRightTrigger >= 30; // TODO: change this to a pressure preference
// these checks are in place to improve responsiveness of square/X while right trigger is held down
if (xRisingEdge && rtPulled)
xCancelUntilTick = SDL_GetTicks() + GetBoostCancelDurationMs();
bool inCancelWindow = SDL_TICKS_PASSED(xCancelUntilTick, SDL_GetTicks());
if (inCancelWindow)
pad.wButtons &= ~XAMINPUT_GAMEPAD_X;
else if (xHeldPhysically || rtPulled)
pad.wButtons |= XAMINPUT_GAMEPAD_X;
else
pad.wButtons &= ~XAMINPUT_GAMEPAD_X;
if (rtPulled)
pad.bRightTrigger = 0;
xWasHeldLastPoll = xHeldPhysically;
}
}
void Poll()
@ -129,6 +175,34 @@ public:
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_B, XAMINPUT_GAMEPAD_B);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_X, XAMINPUT_GAMEPAD_X);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_Y, XAMINPUT_GAMEPAD_Y);
// when playing day stages keep the right trigger mirrored onto square/X
// so so the game knows the user is boosting. This will remove the actual
// right trigger from the game so sonic wouldn't drift
if (IsBoostOnRightTriggerActive())
{
bool xHeldPhysically = (pad.wButtons & XAMINPUT_GAMEPAD_X) != 0;
bool xRisingEdge = xHeldPhysically && !xWasHeldLastPoll;
uint8_t rtRaw = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7;
bool rtPulled = rtRaw >= 30; // TODO: change this to a pressure preference
// like in Poll() these checks are in place to improve responsiveness
// of square/X while right trigger is held down
if (xRisingEdge && rtPulled)
xCancelUntilTick = SDL_GetTicks() + GetBoostCancelDurationMs();
bool inCancelWindow = SDL_TICKS_PASSED(xCancelUntilTick, SDL_GetTicks());
if (inCancelWindow)
pad.wButtons &= ~XAMINPUT_GAMEPAD_X;
else if (rtPulled)
pad.wButtons |= XAMINPUT_GAMEPAD_X;
if (rtPulled)
pad.bRightTrigger = 0;
xWasHeldLastPoll = xHeldPhysically;
}
}
void SetVibration(const XAMINPUT_VIBRATION& vibration)

View file

@ -216,6 +216,66 @@ CONFIG_DEFINE_ENUM_LOCALE(ETimeOfDayTransition)
}
};
// Translation required
// Japanese Notes: This localization should include furigana in its description.
CONFIG_DEFINE_LOCALE(RightTriggerAction)
{
{ ELanguage::English, { "Right Trigger Action", "Choose what the right trigger does in day stages." } },
{ ELanguage::Japanese, { "Right Trigger Action", "Choose what the right trigger does in day stages." } }, // Translation required
{ ELanguage::German, { "Right Trigger Action", "Choose what the right trigger does in day stages." } }, // Translation required
{ ELanguage::French, { "Right Trigger Action", "Choose what the right trigger does in day stages." } }, // Translation required
{ ELanguage::Spanish, { "Right Trigger Action", "Choose what the right trigger does in day stages." } }, // Translation required
{ ELanguage::Italian, { "Right Trigger Action", "Choose what the right trigger does in day stages." } } // Translation required
};
// Translation required
// Japanese Notes: This localization should include furigana in its description.
CONFIG_DEFINE_ENUM_LOCALE(ERightTriggerAction)
{
{
ELanguage::English,
{
{ ERightTriggerAction::Drift, { "DRIFT", "Default: the right trigger acts as drift, matching the original Xbox 360/PS3 controls." } },
{ ERightTriggerAction::Boost, { "BOOST/H.A", "EXPERIMENTAL: The right trigger acts as boost or homing attack. Drift is still available on the left trigger and X/Square still triggers boost too." } }
}
},
{
ELanguage::Japanese,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
},
{
ELanguage::German,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
},
{
ELanguage::French,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
},
{
ELanguage::Spanish,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
},
{
ELanguage::Italian,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
}
};
// Japanese Notes: This localization should include furigana.
CONFIG_DEFINE_LOCALE(ControllerIcons)
{

View file

@ -30,6 +30,12 @@ CONFIG_DEFINE_ENUM_TEMPLATE(ECameraRotationMode)
{ "Reverse", ECameraRotationMode::Reverse },
};
CONFIG_DEFINE_ENUM_TEMPLATE(ERightTriggerAction)
{
{ "Drift", ERightTriggerAction::Drift },
{ "Boost", ERightTriggerAction::Boost }
};
CONFIG_DEFINE_ENUM_TEMPLATE(EControllerIcons)
{
{ "Auto", EControllerIcons::Auto },

View file

@ -52,6 +52,12 @@ enum class ECameraRotationMode : uint32_t
Reverse
};
enum class ERightTriggerAction : uint32_t
{
Drift,
Boost
};
enum class EControllerIcons : uint32_t
{
Auto,

View file

@ -12,6 +12,7 @@ CONFIG_DEFINE("System", bool, ShowConsole, false);
CONFIG_DEFINE_ENUM_LOCALISED("Input", ECameraRotationMode, HorizontalCamera, ECameraRotationMode::Normal);
CONFIG_DEFINE_ENUM_LOCALISED("Input", ECameraRotationMode, VerticalCamera, ECameraRotationMode::Normal);
CONFIG_DEFINE_ENUM_LOCALISED("Input", ERightTriggerAction, RightTriggerAction, ERightTriggerAction::Drift);
CONFIG_DEFINE_LOCALISED("Input", bool, Vibration, true);
CONFIG_DEFINE_LOCALISED("Input", bool, AllowBackgroundInput, false);
CONFIG_DEFINE_ENUM_LOCALISED("Input", EControllerIcons, ControllerIcons, EControllerIcons::Auto);