Add a controller look acceleration toggle

Controller aiming always ramped toward the requested turn rate, preventing
players from choosing an immediate response to right-stick input.

Add an Enabled/Disabled Look Acceleration control to the Controller menu
and persist it through settings load/save and native menu dvars. Forward
the setting to the aiming code: disabling it applies the requested angular
velocity immediately, including when switching off an active ramp.

Keep acceleration enabled by default for existing configurations. Preserve
response curves, sensitivity scaling, ADS blending and FOV scaling.

Validation: the play build and targeted formatting checks passed. Temporary
probes checked immediate turning, the existing acceleration ramp, switching
off mid-ramp, and ADS/FOV scaling at 30, 60 and 144 Hz. Menu inheritance and
the toggle choices were also checked. Physical-controller feel has not
been retested in game.
This commit is contained in:
awsms
2026-10-01 07:33:59 +02:00
parent 11514ea37d
commit 05e8075c59
6 changed files with 106 additions and 14 deletions
+1
View File
@@ -411,6 +411,7 @@ fn publish_client_action_input(
out.pad_sensitivity =
settings.pad_sensitivity / frame::GameSettings::PAD_SENSITIVITY_DEFAULT;
out.pad_ads_sensitivity = settings.pad_ads_sensitivity;
out.pad_acceleration = settings.pad_acceleration;
if let Some(pad) = pad {
let sticks = crate::gamepad::sticks(pad, &settings);
physical.movement_ready |= sticks.movement == Vec2::ZERO;
+7
View File
@@ -358,6 +358,7 @@ fn serialize_settings(settings: &frame::GameSettings, binds: &KeyBinds) -> Strin
format!("pad_ads_sensitivity={:.2}", settings.pad_ads_sensitivity),
format!("pad_invert={}", settings.pad_invert),
format!("pad_curve={}", settings.pad_curve),
format!("pad_acceleration={}", settings.pad_acceleration),
format!("pad_aim_assist={}", settings.pad_aim_assist),
format!("pad_prompts={}", settings.pad_prompts),
format!("pad_vibration={}", settings.pad_vibration),
@@ -451,6 +452,7 @@ fn parse_settings(source: &str, settings: &mut frame::GameSettings, binds: &mut
"pad_ads_sensitivity" => parse_into(value, &mut settings.pad_ads_sensitivity),
"pad_invert" => parse_into(value, &mut settings.pad_invert),
"pad_curve" => parse_into(value, &mut settings.pad_curve),
"pad_acceleration" => parse_into(value, &mut settings.pad_acceleration),
"pad_aim_assist" => parse_into(value, &mut settings.pad_aim_assist),
"pad_prompts" => parse_into(value, &mut settings.pad_prompts),
"pad_vibration" => parse_into(value, &mut settings.pad_vibration),
@@ -534,6 +536,7 @@ pub(crate) fn native_menu_settings(
"ui_pad_ads_sensitivity" => parse_into(value, &mut settings.pad_ads_sensitivity),
"ui_pad_invert" => settings.pad_invert = value == "1",
"ui_pad_curve" => parse_into(value, &mut settings.pad_curve),
"ui_pad_acceleration" => settings.pad_acceleration = value == "1",
"ui_pad_aim_assist" => parse_into(value, &mut settings.pad_aim_assist),
"ui_pad_prompts" => parse_into(value, &mut settings.pad_prompts),
"ui_pad_test_rumble" => {
@@ -576,6 +579,10 @@ pub(crate) fn native_menu_settings(
);
dvars.set("ui_pad_invert", if settings.pad_invert { "1" } else { "0" });
dvars.set("ui_pad_curve", settings.pad_curve.to_string());
dvars.set(
"ui_pad_acceleration",
if settings.pad_acceleration { "1" } else { "0" },
);
dvars.set("ui_pad_aim_assist", settings.pad_aim_assist.to_string());
dvars.set("ui_pad_prompts", settings.pad_prompts.to_string());
dvars.set(
+2
View File
@@ -44,6 +44,7 @@ pub struct GameSettings {
pub pad_ads_sensitivity: f32,
pub pad_invert: bool,
pub pad_curve: u8,
pub pad_acceleration: bool,
pub pad_aim_assist: u8,
pub pad_prompts: u8,
pub pad_vibration: bool,
@@ -74,6 +75,7 @@ impl Default for GameSettings {
pad_ads_sensitivity: 1.0,
pad_invert: false,
pad_curve: 0,
pad_acceleration: true,
pad_aim_assist: 0,
pad_prompts: 0,
pad_vibration: true,
+2
View File
@@ -55,6 +55,7 @@ pub struct ClientActionInput {
pub pad_look: [f32; 2],
pub pad_deflection: f32,
pub pad_sensitivity: f32,
pub pad_acceleration: bool,
pub pad_ads_sensitivity: f32,
pub pad_turn_rate: [f32; 2],
/// Pitch and yaw, degrees.
@@ -89,6 +90,7 @@ impl Default for ClientActionInput {
pad_look: [0.0; 2],
pad_deflection: 0.0,
pad_sensitivity: 1.0,
pad_acceleration: true,
pad_ads_sensitivity: 1.0,
pad_turn_rate: [0.0; 2],
pad_look_delta: [0.0; 2],
+3 -2
View File
@@ -171,8 +171,9 @@ pub fn pad_look_frame(
let wanted = [-input.pad_look[1] * max_pitch, -input.pad_look[0] * max_yaw];
for (rate, goal) in input.pad_turn_rate.iter_mut().zip(wanted) {
if (goal.abs() > rate.abs() && goal.signum() == rate.signum())
|| (*rate == 0.0 && goal != 0.0)
if input.pad_acceleration
&& ((goal.abs() > rate.abs() && goal.signum() == rate.signum())
|| (*rate == 0.0 && goal != 0.0))
{
let step = TURN_ACCEL * zoom * dt;
*rate = if goal > *rate {
+91 -12
View File
@@ -559,6 +559,85 @@
"name": "controller_label_11"
}
},
{
"name": "video_display_mode",
"fields": {
"item_type": 12,
"static_flags": 0,
"dvar": "ui_pad_acceleration",
"choices": [
[
"@MENU_DISABLED",
"0"
],
[
"@MENU_ENABLED",
"1"
]
],
"vis_exp": "1",
"disabled_exp": "0",
"text_key": "",
"text_exp": "",
"text_align_mode": 10,
"text_align_x": -8,
"text_align_y": 0,
"fore_color": [
1,
1,
1,
1
],
"rect": {
"x": 232,
"y": 148,
"w": 344,
"h": 20
},
"handlers": {
"action": [
{
"Script": "play mouse_click;"
}
],
"focus": [
{
"Script": "play mouse_over; setItemColor self backcolor 0 0 0 1;"
}
],
"leave_focus": [
{
"Script": "setItemColor self backcolor 0 0 0 0;"
}
]
},
"text_scale": 0.375,
"style": 1,
"background": "menu_button_selection_bar",
"back_color": [
0,
0,
0,
0
],
"name": "ui_pad_acceleration"
}
},
{
"name": "video_display_mode_label",
"fields": {
"vis_exp": "1",
"text_key": "Look Acceleration",
"rect": {
"x": 232,
"y": 148,
"w": 344,
"h": 20
},
"text_scale": 0.32,
"name": "controller_acceleration_label"
}
},
{
"name": "video_display_mode",
"fields": {
@@ -586,7 +665,7 @@
],
"rect": {
"x": 232,
"y": 148,
"y": 168,
"w": 344,
"h": 20
},
@@ -626,7 +705,7 @@
"text_key": "Aim Assist",
"rect": {
"x": 232,
"y": 148,
"y": 168,
"w": 344,
"h": 20
},
@@ -665,7 +744,7 @@
],
"rect": {
"x": 232,
"y": 168,
"y": 188,
"w": 344,
"h": 20
},
@@ -705,7 +784,7 @@
"text_key": "Vibration",
"rect": {
"x": 232,
"y": 168,
"y": 188,
"w": 344,
"h": 20
},
@@ -735,7 +814,7 @@
],
"rect": {
"x": 420,
"y": 188,
"y": 208,
"w": 112,
"h": 20
},
@@ -775,7 +854,7 @@
"vis_exp": "1",
"rect": {
"x": 232,
"y": 188,
"y": 208,
"w": 344,
"h": 20
},
@@ -804,7 +883,7 @@
],
"rect": {
"x": 420,
"y": 208,
"y": 228,
"w": 112,
"h": 20
},
@@ -844,7 +923,7 @@
"vis_exp": "1",
"rect": {
"x": 232,
"y": 208,
"y": 228,
"w": 344,
"h": 20
},
@@ -890,7 +969,7 @@
],
"rect": {
"x": 232,
"y": 228,
"y": 248,
"w": 344,
"h": 20
},
@@ -930,7 +1009,7 @@
"text_key": "Controller Prompts",
"rect": {
"x": 232,
"y": 228,
"y": 248,
"w": 344,
"h": 20
},
@@ -960,7 +1039,7 @@
],
"rect": {
"x": 232,
"y": 248,
"y": 268,
"w": 344,
"h": 20
},
@@ -1000,7 +1079,7 @@
"text_key": "Test Vibration",
"rect": {
"x": 232,
"y": 248,
"y": 268,
"w": 344,
"h": 20
},