From e810d2e75b7c29ba425a863e122a83a8bfea0ee8 Mon Sep 17 00:00:00 2001 From: Richard Aasa Date: Thu, 10 Sep 2026 19:17:47 +0300 Subject: [PATCH] Fix vibration going dead for the rest of the session after the gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Siim reported controller vibration stops working entirely after the first playthrough. The gate's pulsed rumble (vibrate_for) fired a new ~0.3s vibration every 0.4s for 7 seconds — about 17 back-to-back start calls. On at least one setup that appears to leave the gamepad's rumble motor stuck reporting "busy", so every later vibrate() call (hits included) silently does nothing for the rest of that session. Space pulses out more (fewer, longer gaps: 0.25s on / 0.6s off instead of 0.3s on / 0.1s off) and explicitly stop_joy_vibration() between them on native instead of relying on each pulse's own duration to time out, so a new effect never starts before the last one has cleanly ended. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01MXBNaEBmrYDSMcv4NgUWtV --- systems/input/controls_manager.gd | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/systems/input/controls_manager.gd b/systems/input/controls_manager.gd index 17db707..cd0da6e 100644 --- a/systems/input/controls_manager.gd +++ b/systems/input/controls_manager.gd @@ -269,12 +269,19 @@ func vibrate(device: int, weak_magnitude: float, strong_magnitude: float, durati ## effect and make it repeat instead." That's exactly what broke the lobby gate's 7-second ## rumble (the short 0.2 s hit-vibration works fine): this repeats vibrate() as short pulses ## to cover the same total duration instead of one long call. +## Explicitly stopping between pulses (rather than letting each one time out on its own) and +## spacing them out avoids re-triggering the effect faster than some drivers/browsers can +## retire the previous one — back-to-back-to-back start calls left the gamepad's rumble +## motor stuck reporting "busy" for the rest of the session on at least one setup. func vibrate_for(device: int, weak_magnitude: float, strong_magnitude: float, - total_duration: float, pulse: float = 0.3, gap: float = 0.1) -> void: + total_duration: float, pulse: float = 0.25, gap: float = 0.6) -> void: var elapsed := 0.0 while elapsed < total_duration: vibrate(device, weak_magnitude, strong_magnitude, pulse) - await get_tree().create_timer(pulse + gap).timeout + await get_tree().create_timer(pulse).timeout + if not OS.has_feature("web"): + Input.stop_joy_vibration(device) + await get_tree().create_timer(gap).timeout elapsed += pulse + gap