mirror of
https://github.com/vladtrc/iw4L
synced 2026-10-26 02:11:39 -04:00
Separate controller presets from custom sensitivity
The fine sensitivity slider reused the 1-10 setting, conflating console preset numbers with a continuous speed control. Selecting a preset must leave the player's custom slider value available for later use. Store the selected preset and custom multiplier independently. Add Custom and integer choices 1 through 10 to the Controller menu. Use the IW4x pc_options_gamepad.menu preset table: 0.6, 1.0, 1.4, 1.8, 2.0, 2.2, 2.6, 3.0, 3.5 and 4.0. Custom uses the local controller slider's 0.1-5.0 multiplier range with 0.1 steps. Editing the slider selects Custom; selecting a preset never overwrites the saved custom value. Resolve the active multiplier before applying controller aiming. Persist both settings and migrate the previous pad_sensitivity value to Custom using its old value/3 speed mapping, preserving existing effective speed. The acceleration toggle remains independent. Validation: play build, targeted formatting and diff checks passed. Temporary probes verified all ten preset multipliers, custom-value retention, settings save/reload and legacy migration, and menu inheritance/choices. Aiming probes also passed for acceleration on/off and ADS/FOV scaling at 30, 60 and 144 Hz. Gameplay feel and visual layout were not retested.
This commit is contained in:
@@ -408,8 +408,7 @@ fn publish_client_action_input(
|
||||
physical.movement_ready = false;
|
||||
physical.look_ready = false;
|
||||
} else {
|
||||
out.pad_sensitivity =
|
||||
settings.pad_sensitivity / frame::GameSettings::PAD_SENSITIVITY_DEFAULT;
|
||||
out.pad_sensitivity = settings.pad_look_sensitivity();
|
||||
out.pad_ads_sensitivity = settings.pad_ads_sensitivity;
|
||||
out.pad_acceleration = settings.pad_acceleration;
|
||||
if let Some(pad) = pad {
|
||||
|
||||
@@ -354,7 +354,11 @@ fn serialize_settings(settings: &frame::GameSettings, binds: &KeyBinds) -> Strin
|
||||
format!("player_name={safe_name}"),
|
||||
format!("pad_layout={}", settings.pad_layout),
|
||||
format!("pad_stick_layout={}", settings.pad_stick_layout),
|
||||
format!("pad_sensitivity={:.2}", settings.pad_sensitivity),
|
||||
format!("pad_sensitivity_preset={}", settings.pad_sensitivity_preset),
|
||||
format!(
|
||||
"pad_custom_sensitivity={:.3}",
|
||||
settings.pad_custom_sensitivity
|
||||
),
|
||||
format!("pad_ads_sensitivity={:.2}", settings.pad_ads_sensitivity),
|
||||
format!("pad_invert={}", settings.pad_invert),
|
||||
format!("pad_curve={}", settings.pad_curve),
|
||||
@@ -448,7 +452,15 @@ fn parse_settings(source: &str, settings: &mut frame::GameSettings, binds: &mut
|
||||
"player_name" => settings.player_name = value.to_owned(),
|
||||
"pad_layout" => parse_into(value, &mut settings.pad_layout),
|
||||
"pad_stick_layout" => parse_into(value, &mut settings.pad_stick_layout),
|
||||
"pad_sensitivity" => parse_into(value, &mut settings.pad_sensitivity),
|
||||
// Preserve the effective speed of configs saved with the old 1-10 slider.
|
||||
"pad_sensitivity" => {
|
||||
if let Ok(old) = value.parse::<f32>() {
|
||||
settings.pad_custom_sensitivity = old.clamp(1.0, 10.0) / 3.0;
|
||||
settings.pad_sensitivity_preset = 0;
|
||||
}
|
||||
}
|
||||
"pad_sensitivity_preset" => parse_into(value, &mut settings.pad_sensitivity_preset),
|
||||
"pad_custom_sensitivity" => parse_into(value, &mut settings.pad_custom_sensitivity),
|
||||
"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),
|
||||
@@ -532,7 +544,11 @@ pub(crate) fn native_menu_settings(
|
||||
"ui_bloom" => settings.bloom = value == "1",
|
||||
"ui_pad_layout" => parse_into(value, &mut settings.pad_layout),
|
||||
"ui_pad_stick_layout" => parse_into(value, &mut settings.pad_stick_layout),
|
||||
"ui_pad_sensitivity" => parse_into(value, &mut settings.pad_sensitivity),
|
||||
"ui_pad_sensitivity_preset" => parse_into(value, &mut settings.pad_sensitivity_preset),
|
||||
"ui_pad_custom_sensitivity" => {
|
||||
parse_into(value, &mut settings.pad_custom_sensitivity);
|
||||
settings.pad_sensitivity_preset = 0;
|
||||
}
|
||||
"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),
|
||||
@@ -572,7 +588,14 @@ pub(crate) fn native_menu_settings(
|
||||
dvars.set("ui_r_vsync", if settings.vsync { "1" } else { "0" });
|
||||
dvars.set("ui_pad_layout", settings.pad_layout.to_string());
|
||||
dvars.set("ui_pad_stick_layout", settings.pad_stick_layout.to_string());
|
||||
dvars.set("ui_pad_sensitivity", settings.pad_sensitivity.to_string());
|
||||
dvars.set(
|
||||
"ui_pad_sensitivity_preset",
|
||||
settings.pad_sensitivity_preset.to_string(),
|
||||
);
|
||||
dvars.set(
|
||||
"ui_pad_custom_sensitivity",
|
||||
settings.pad_custom_sensitivity.to_string(),
|
||||
);
|
||||
dvars.set(
|
||||
"ui_pad_ads_sensitivity",
|
||||
settings.pad_ads_sensitivity.to_string(),
|
||||
|
||||
@@ -40,7 +40,9 @@ pub struct GameSettings {
|
||||
|
||||
pub pad_layout: u8,
|
||||
pub pad_stick_layout: u8,
|
||||
pub pad_sensitivity: f32,
|
||||
/// Zero selects the independently saved custom multiplier; 1..=10 select presets.
|
||||
pub pad_sensitivity_preset: u8,
|
||||
pub pad_custom_sensitivity: f32,
|
||||
pub pad_ads_sensitivity: f32,
|
||||
pub pad_invert: bool,
|
||||
pub pad_curve: u8,
|
||||
@@ -71,7 +73,8 @@ impl Default for GameSettings {
|
||||
player_name: "Player".to_owned(),
|
||||
pad_layout: 0,
|
||||
pad_stick_layout: 0,
|
||||
pad_sensitivity: Self::PAD_SENSITIVITY_DEFAULT,
|
||||
pad_sensitivity_preset: 0,
|
||||
pad_custom_sensitivity: 1.0,
|
||||
pad_ads_sensitivity: 1.0,
|
||||
pad_invert: false,
|
||||
pad_curve: 0,
|
||||
@@ -90,7 +93,18 @@ impl GameSettings {
|
||||
pub const FOV_DEFAULT: f32 = 65.0;
|
||||
pub const FOV_MIN: f32 = 65.0;
|
||||
pub const FOV_MAX: f32 = 120.0;
|
||||
pub const PAD_SENSITIVITY_DEFAULT: f32 = 3.0;
|
||||
// IW4x ui_mp/pc_options_gamepad.menu: SENSITIVITY_1 through SENSITIVITY_10.
|
||||
pub const PAD_SENSITIVITY_PRESETS: [f32; 10] =
|
||||
[0.6, 1.0, 1.4, 1.8, 2.0, 2.2, 2.6, 3.0, 3.5, 4.0];
|
||||
|
||||
pub fn pad_look_sensitivity(&self) -> f32 {
|
||||
self.pad_sensitivity_preset
|
||||
.checked_sub(1)
|
||||
.and_then(|index| Self::PAD_SENSITIVITY_PRESETS.get(usize::from(index)))
|
||||
.copied()
|
||||
.unwrap_or(self.pad_custom_sensitivity)
|
||||
}
|
||||
|
||||
pub const PAD_LAYOUT_CUSTOM: u8 = 255;
|
||||
|
||||
pub fn touch(&mut self) {
|
||||
@@ -126,12 +140,8 @@ impl GameSettings {
|
||||
default
|
||||
}
|
||||
};
|
||||
self.pad_sensitivity = finite(
|
||||
self.pad_sensitivity,
|
||||
1.0,
|
||||
10.0,
|
||||
Self::PAD_SENSITIVITY_DEFAULT,
|
||||
);
|
||||
self.pad_sensitivity_preset = self.pad_sensitivity_preset.min(10);
|
||||
self.pad_custom_sensitivity = finite(self.pad_custom_sensitivity, 0.1, 5.0, 1.0);
|
||||
self.pad_ads_sensitivity = finite(self.pad_ads_sensitivity, 0.5, 1.5, 1.0);
|
||||
self.pad_deadzone_left = finite(self.pad_deadzone_left, 0.0, 0.4, 0.12);
|
||||
self.pad_deadzone_right = finite(self.pad_deadzone_right, 0.0, 0.4, 0.12);
|
||||
|
||||
+143
-28
@@ -262,12 +262,127 @@
|
||||
"name": "controller_label_3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "video_display_mode",
|
||||
"fields": {
|
||||
"item_type": 12,
|
||||
"static_flags": 0,
|
||||
"dvar": "ui_pad_sensitivity_preset",
|
||||
"choices": [
|
||||
[
|
||||
"Custom",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
"1",
|
||||
"1"
|
||||
],
|
||||
[
|
||||
"2",
|
||||
"2"
|
||||
],
|
||||
[
|
||||
"3",
|
||||
"3"
|
||||
],
|
||||
[
|
||||
"4",
|
||||
"4"
|
||||
],
|
||||
[
|
||||
"5",
|
||||
"5"
|
||||
],
|
||||
[
|
||||
"6",
|
||||
"6"
|
||||
],
|
||||
[
|
||||
"7",
|
||||
"7"
|
||||
],
|
||||
[
|
||||
"8",
|
||||
"8"
|
||||
],
|
||||
[
|
||||
"9",
|
||||
"9"
|
||||
],
|
||||
[
|
||||
"10",
|
||||
"10"
|
||||
]
|
||||
],
|
||||
"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": 68,
|
||||
"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_sensitivity_preset"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "video_display_mode_label",
|
||||
"fields": {
|
||||
"vis_exp": "1",
|
||||
"text_key": "Sensitivity Preset",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 68,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
"text_scale": 0.32,
|
||||
"name": "controller_sensitivity_preset_label"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "video_brightness",
|
||||
"fields": {
|
||||
"item_type": 10,
|
||||
"static_flags": 0,
|
||||
"dvar": "ui_pad_sensitivity",
|
||||
"dvar": "ui_pad_custom_sensitivity",
|
||||
"choices": [],
|
||||
"vis_exp": "1",
|
||||
"disabled_exp": "0",
|
||||
@@ -284,7 +399,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 420,
|
||||
"y": 68,
|
||||
"y": 88,
|
||||
"w": 112,
|
||||
"h": 20
|
||||
},
|
||||
@@ -305,24 +420,24 @@
|
||||
0
|
||||
],
|
||||
"slider": {
|
||||
"min": 1,
|
||||
"max": 10,
|
||||
"min": 0.1,
|
||||
"max": 5.0,
|
||||
"step": 0.1,
|
||||
"display_range": null,
|
||||
"suffix": "",
|
||||
"suffix": "x",
|
||||
"decimals": 1
|
||||
},
|
||||
"name": "ui_pad_sensitivity"
|
||||
"name": "ui_pad_custom_sensitivity"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "video_brightness_label",
|
||||
"fields": {
|
||||
"text_key": "Look Sensitivity",
|
||||
"text_key": "Custom Sensitivity",
|
||||
"vis_exp": "1",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 68,
|
||||
"y": 88,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -351,7 +466,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 420,
|
||||
"y": 88,
|
||||
"y": 108,
|
||||
"w": 112,
|
||||
"h": 20
|
||||
},
|
||||
@@ -391,7 +506,7 @@
|
||||
"vis_exp": "1",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 88,
|
||||
"y": 108,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -429,7 +544,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 108,
|
||||
"y": 128,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -469,7 +584,7 @@
|
||||
"text_key": "Look Inversion",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 108,
|
||||
"y": 128,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -512,7 +627,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 128,
|
||||
"y": 148,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -552,7 +667,7 @@
|
||||
"text_key": "Response Curve",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 128,
|
||||
"y": 148,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -591,7 +706,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 148,
|
||||
"y": 168,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -631,7 +746,7 @@
|
||||
"text_key": "Look Acceleration",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 148,
|
||||
"y": 168,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -666,7 +781,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 168,
|
||||
"y": 188,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -706,7 +821,7 @@
|
||||
"text_key": "Aim Assist",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 168,
|
||||
"y": 188,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -745,7 +860,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 188,
|
||||
"y": 208,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -785,7 +900,7 @@
|
||||
"text_key": "Vibration",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 188,
|
||||
"y": 208,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -815,7 +930,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 420,
|
||||
"y": 208,
|
||||
"y": 228,
|
||||
"w": 112,
|
||||
"h": 20
|
||||
},
|
||||
@@ -855,7 +970,7 @@
|
||||
"vis_exp": "1",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 208,
|
||||
"y": 228,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -884,7 +999,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 420,
|
||||
"y": 228,
|
||||
"y": 248,
|
||||
"w": 112,
|
||||
"h": 20
|
||||
},
|
||||
@@ -924,7 +1039,7 @@
|
||||
"vis_exp": "1",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 228,
|
||||
"y": 248,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -970,7 +1085,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 248,
|
||||
"y": 268,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -1010,7 +1125,7 @@
|
||||
"text_key": "Controller Prompts",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 248,
|
||||
"y": 268,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -1040,7 +1155,7 @@
|
||||
],
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 268,
|
||||
"y": 288,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
@@ -1080,7 +1195,7 @@
|
||||
"text_key": "Test Vibration",
|
||||
"rect": {
|
||||
"x": 232,
|
||||
"y": 268,
|
||||
"y": 288,
|
||||
"w": 344,
|
||||
"h": 20
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user