Skip to content

Add speed-based throttle, surface brake, and turbo lag effects#64

Open
O0rphan wants to merge 5 commits into
HamzaYslmn:mainfrom
O0rphan:trigger-features
Open

Add speed-based throttle, surface brake, and turbo lag effects#64
O0rphan wants to merge 5 commits into
HamzaYslmn:mainfrom
O0rphan:trigger-features

Conversation

@O0rphan
Copy link
Copy Markdown

@O0rphan O0rphan commented May 24, 2026

Three new adaptive trigger effects for Forza Horizon telemetry.

1. Speed-based throttle resistance (R2)

Extra R2 resistance at low speed that fades as the car accelerates.
A flat additive force (default 30) is applied on top of the normal
throttle ramp at standstill, making the trigger heavier for precise
low-speed control. Fades linearly to zero by the configured speed
(default 80 km/h).

Settings: enable_speed_throttle (on), speed_throttle_boost (30, 0=off), speed_throttle_fade_km (80)

2. Surface-type brake resistance (L2)

Modulates L2 brake force based on surface under the wheels. On tarmac
the multiplier is 1.0 (unchanged). On dirt and gravel the final brake
force is scaled down, making the trigger softer to signal reduced grip.
Uses the same surface_rumble / wheel_in_puddle classification as
wheelspin buzz.

Settings: enable_surface_brake (off), surface_brake_tarmac (1.0), surface_brake_dirt (0.5), surface_brake_gravel (0.25)

3. Turbo lag effect (R2)

Brief deep rumble on R2 when boost pressure is climbing. Detects
per-tick boost delta; fires a low-frequency vibrate (8 Hz) whose
amplitude scales with the rate of boost change. A cooldown timer
(300 ms) and threshold (0.15) prevent steady-state telemetry jitter
from triggering false rumbles at constant RPM. Only fires on cars with
a turbo/supercharger (boost > 0).

Settings: enable_turbo_lag (on), turbo_lag_freq (8 Hz), turbo_lag_amp (40), turbo_lag_threshold (0.15), turbo_lag_cooldown_ms (300)

All three are independent — each can be toggled on/off separately.
Translations: ru, tr, zh, ja.

O0rphan added 5 commits May 24, 2026 23:58
At low speed (parking, hairpins) the throttle trigger feels heavier for
more precise inputs; at high speed (highway cruising) it goes lighter
so sustained WOT is comfortable without finger fatigue.

New settings (Settings > Right trigger section):
- enable_speed_throttle: toggle (default on)
- speed_throttle_boost: extra force at 0 km/h (0 = off, default 0)
- speed_throttle_fade_km: speed where boost fully fades (default 80)

When boost > 0, the effective max_force scales from
(throttle_max_force + boost) at 0 km/h down to throttle_max_force
at fade_km. The existing throttle ramp curve is preserved throughout.

Translations added: ru, tr, zh, ja.
Modulates brake trigger stiffness based on the driving surface. On
tarmac the brake feels firm and progressive; on dirt it goes softer
(spongy feel); on gravel/water even softer - matching how real brakes
feel less effective on loose surfaces.

New settings (Settings > Left trigger section):
- enable_surface_brake: toggle (default off)
- surface_brake_tarmac: multiplier on tarmac (1.0 = unchanged)
- surface_brake_dirt: multiplier on dirt (default 0.7)
- surface_brake_gravel: multiplier on gravel/water (default 0.5)

Reuses the same surface classification from wheelspin_buzz (surface_rumble
+ wheel_in_puddle). Both baseline and max force are scaled by the
multiplier before the ramp is computed. Only active while braking.

Translations added: ru, tr, zh, ja.
Brief deep vibration on R2 when boost pressure is actively climbing,
simulating the moment of lag before full turbo power kicks in. Silent
at steady-state boost or zero boost.

Uses the existing boost field (0.0-1.0) from Forza telemetry.
Delta detection: only fires when (current_boost - previous_boost)
exceeds a configurable threshold. Amplitude scales with the rate of
boost increase.

New settings (Settings > Turbo lag section):
- enable_turbo_lag: toggle (default on)
- turbo_lag_freq: vibration frequency in Hz (default 8, deep rumble)
- turbo_lag_amp: max amplitude (default 40)
- turbo_lag_threshold: min boost delta per tick (default 0.05)

R2 priority chain updated: gear shift > idle > rev limiter > wheelspin
> turbo lag > end wall > throttle ramp.

Translations added: ru, tr, zh, ja.
Copilot AI review requested due to automatic review settings May 24, 2026 19:50
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds new Forza Horizon trigger effects and exposes them in both GUI/TUI settings, including localized strings.

Changes:

  • Added surface-aware brake resistance multipliers (tarmac/dirt/gravel).
  • Added speed-based throttle resistance (extra force at low speed that fades with speed).
  • Added turbo-lag R2 rumble based on rising boost pressure + cooldown, plus new i18n strings.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/modules/tui/settings_tab.py Adds new settings sections/options for surface brake, speed throttle, and turbo lag.
src/modules/gui/settings_tab.py Mirrors the new settings sections/options in the GUI.
src/modules/forzahorizon/effects.py Implements turbo lag rumble, surface-based brake scaling, and speed-based throttle scaling.
src/modules/config/settings.py Introduces new Settings fields and defaults for the added effects.
src/lang/zh.py Adds translations for new settings strings.
src/lang/tr.py Adds translations for new settings strings (contains a unit issue noted below).
src/lang/ru.py Adds translations for new settings strings.
src/lang/ja.py Adds translations for new settings strings.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +144 to +157
def turbo_lag(self, t, s, now):
if not s.enable_turbo_lag:
self._prev_boost = t["boost"]
return None
boost = t["boost"]
delta = boost - self._prev_boost
self._prev_boost = boost
if delta < s.turbo_lag_threshold or boost < 0.1:
return None
if now - self._turbo_last_fire < s.turbo_lag_cooldown_ms / 1000.0:
return None
self._turbo_last_fire = now
amp = min(255, int(s.turbo_lag_amp * min(delta / 0.2, 1.0)))
return vibrate(s.turbo_lag_freq, amp)
Comment on lines 170 to 190
handbrake = s.enable_handbrake_bonus and t["handbrake"]
if not s.enable_brake_resistance:
return rigid(s.handbrake_bonus) if handbrake else off()
force = _ramp(t["brake"], s.brake_deadzone, s.brake_baseline_force,
s.brake_max_force, s.brake_curve, s.brake_wall_engage_at)
if s.enable_surface_brake and t["brake"] > 0:
wheels = DRIVEN_WHEELS.get(t["drive_train"], ("fl", "fr", "rl", "rr"))
if any(t[f"wheel_in_puddle_{w}"] > 0 for w in wheels):
mult = s.surface_brake_gravel
else:
rumble = max(abs(t[f"surface_rumble_{w}"]) for w in wheels)
if rumble > 0.30:
mult = s.surface_brake_gravel
elif rumble > 0.10:
mult = s.surface_brake_dirt
else:
mult = s.surface_brake_tarmac
force = max(0, int(force * mult))
if handbrake:
force += s.handbrake_bonus
return rigid(force)
Comment on lines +64 to +69
# MARK: R2 speed-based throttle
# Extra throttle resistance at low speed; fades as speed rises.
# boost=0 means off (no extra force). Flat additive at 0 km/h, fading to normal by fade_km.
enable_speed_throttle: bool = True
speed_throttle_boost: int = 30 # extra force added at standstill (0 = off)
speed_throttle_fade_km: float = 80.0 # speed where boost fully fades
Comment thread src/lang/tr.py
"Yeni dili uygulamak için uygulamayı yeniden başlatın.",
"Speed-based throttle": "Hıza dayalı gaz",
"Extra force at standstill": "Dururken ekstra kuvvet",
"Fade-out speed (km/h)": "Sönme hızı (km/s)",
Comment thread src/lang/tr.py
Comment on lines +133 to +134
"0 = off. Flat resistance added at 0 km/h, fading to normal.":
"0 = kapalı. 0 km/s'de düz direnç eklenir, normale kadar sönür.",
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants