diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 206a20d..de9caef 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -60,10 +60,10 @@ jobs: echo "Manifests OK" - name: Config keys run: | - for key in DEADZONE GAMMA STEER_SMOOTH SPEED_SCALE_START SPEED_SCALE_END SPEED_SCALE_MIN COUNTERSTEER_GAIN COUNTERSTEER_DAMP SLIP_LIMIT_START SLIP_LIMIT_RANGE SLIP_LIMIT_MIN GAS_DEADZONE GAS_GAMMA BRAKE_DEADZONE BRAKE_GAMMA HAPTICS_ENABLED HAPTICS_SLIP_START HAPTICS_SLIP_MAX HAPTICS_STRENGTH DEBUG_MODE; do + for key in DEADZONE GAMMA STEER_SMOOTH STEER_SMOOTH_MIN SPEED_SCALE_START SPEED_SCALE_END SPEED_SCALE_MIN YAW_GAIN YAW_DAMP SLIP_DELTA_THRESH US_REDUCTION OS_BOOST SLIP_LIMIT_START SLIP_LIMIT_RANGE SLIP_LIMIT_MIN GAS_DEADZONE GAS_GAMMA BRAKE_DEADZONE BRAKE_GAMMA TC_ENABLED HAPTICS_ENABLED HAPTICS_SLIP_START HAPTICS_SLIP_MAX HAPTICS_STRENGTH DEBUG_MODE; do grep -q "$key" MyGamepadFX/config.lua || { echo "FAIL: config.lua missing $key"; exit 1; } done - echo "All 20 config keys present" + echo "All 25 config keys present" comment: name: PR Comment diff --git a/MyGamepadFX/assist.lua b/MyGamepadFX/assist.lua index c07503d..8c5f245 100644 --- a/MyGamepadFX/assist.lua +++ b/MyGamepadFX/assist.lua @@ -1,6 +1,9 @@ -- assist.lua — pipeline assembly and CSP entry points -- Pipeline (execution order): --- raw input → calibrate → deadzone/gamma → speed scale → slip limit (driver only) → + self-steer → smooth → clamp → output +-- raw input → calibrate → deadzone/gamma → speed scale +-- → slip classify → understeer clamp → slip limit +-- + yaw damp (oversteer boost, load transfer) +-- → adaptive smooth → clamp → output local CFG = require('config') local lib = require('lib') @@ -10,10 +13,8 @@ local steerOut = 0.0 local frameCount = 0 local firstFrameDiagnostics = false --- Live config: the MyGamepadFX Config app writes this file; we poll it every 0.5s. --- When absent (no app open yet), CFG defaults from config.lua are used unchanged. local LIVE_CFG_PATH = ac.getFolder(ac.FolderID.ScriptOrigin) .. '/live_cfg.ini' -local liveCfgTimer = 0.5 -- start first check after 0.5s to avoid startup noise +local liveCfgTimer = 0.5 local function applyLiveCfg() local ok, ini = pcall(ac.INIConfig.load, LIVE_CFG_PATH) @@ -27,11 +28,15 @@ local function applyLiveCfg() CFG.DEADZONE = ini:get('PARAMS', 'DEADZONE', CFG.DEADZONE) CFG.GAMMA = ini:get('PARAMS', 'GAMMA', CFG.GAMMA) CFG.STEER_SMOOTH = ini:get('PARAMS', 'STEER_SMOOTH', CFG.STEER_SMOOTH) + CFG.STEER_SMOOTH_MIN = ini:get('PARAMS', 'STEER_SMOOTH_MIN', CFG.STEER_SMOOTH_MIN) CFG.SPEED_SCALE_START = ini:get('PARAMS', 'SPEED_SCALE_START', CFG.SPEED_SCALE_START) CFG.SPEED_SCALE_END = ini:get('PARAMS', 'SPEED_SCALE_END', CFG.SPEED_SCALE_END) CFG.SPEED_SCALE_MIN = ini:get('PARAMS', 'SPEED_SCALE_MIN', CFG.SPEED_SCALE_MIN) - CFG.COUNTERSTEER_GAIN = ini:get('PARAMS', 'COUNTERSTEER_GAIN', CFG.COUNTERSTEER_GAIN) - CFG.COUNTERSTEER_DAMP = ini:get('PARAMS', 'COUNTERSTEER_DAMP', CFG.COUNTERSTEER_DAMP) + CFG.YAW_GAIN = ini:get('PARAMS', 'YAW_GAIN', CFG.YAW_GAIN) + CFG.YAW_DAMP = ini:get('PARAMS', 'YAW_DAMP', CFG.YAW_DAMP) + CFG.SLIP_DELTA_THRESH = ini:get('PARAMS', 'SLIP_DELTA_THRESH', CFG.SLIP_DELTA_THRESH) + CFG.US_REDUCTION = ini:get('PARAMS', 'US_REDUCTION', CFG.US_REDUCTION) + CFG.OS_BOOST = ini:get('PARAMS', 'OS_BOOST', CFG.OS_BOOST) CFG.SLIP_LIMIT_START = ini:get('PARAMS', 'SLIP_LIMIT_START', CFG.SLIP_LIMIT_START) CFG.SLIP_LIMIT_RANGE = ini:get('PARAMS', 'SLIP_LIMIT_RANGE', CFG.SLIP_LIMIT_RANGE) CFG.SLIP_LIMIT_MIN = ini:get('PARAMS', 'SLIP_LIMIT_MIN', CFG.SLIP_LIMIT_MIN) @@ -39,6 +44,9 @@ local function applyLiveCfg() CFG.GAS_GAMMA = ini:get('PARAMS', 'GAS_GAMMA', CFG.GAS_GAMMA) CFG.BRAKE_DEADZONE = ini:get('PARAMS', 'BRAKE_DEADZONE', CFG.BRAKE_DEADZONE) CFG.BRAKE_GAMMA = ini:get('PARAMS', 'BRAKE_GAMMA', CFG.BRAKE_GAMMA) + CFG.TC_ENABLED = ini:get('PARAMS', 'TC_ENABLED', CFG.TC_ENABLED) + CFG.TC_SLIP_THRESHOLD = ini:get('PARAMS', 'TC_SLIP_THRESHOLD', CFG.TC_SLIP_THRESHOLD) + CFG.TC_MAX_REDUCTION = ini:get('PARAMS', 'TC_MAX_REDUCTION', CFG.TC_MAX_REDUCTION) CFG.HAPTICS_ENABLED = ini:get('PARAMS', 'HAPTICS_ENABLED', CFG.HAPTICS_ENABLED) CFG.HAPTICS_SLIP_START = ini:get('PARAMS', 'HAPTICS_SLIP_START', CFG.HAPTICS_SLIP_START) CFG.HAPTICS_SLIP_MAX = ini:get('PARAMS', 'HAPTICS_SLIP_MAX', CFG.HAPTICS_SLIP_MAX) @@ -49,7 +57,6 @@ end function script.update(dt) frameCount = frameCount + 1 - -- Poll live_cfg.ini written by the MyGamepadFX Config app (if open) liveCfgTimer = liveCfgTimer - dt if liveCfgTimer <= 0 then liveCfgTimer = 0.5 @@ -59,7 +66,7 @@ function script.update(dt) local car = ac.getCar(0) if not car then if frameCount > 2 then - lib.logOnce("car_nil", "[MyGamepadFX] ERROR: ac.getCar(0) returned nil after startup. Check CM → Settings → Custom Shaders Patch → Gamepad FX → confirm Active and MyGamepadFX selected.") + lib.logOnce("car_nil", "[MyGamepadFX] ERROR: ac.getCar(0) returned nil after startup. Check CM \xE2\x86\x92 Settings \xE2\x86\x92 Custom Shaders Patch \xE2\x86\x92 Gamepad FX \xE2\x86\x92 confirm Active and MyGamepadFX selected.") end steerOut = 0.0 return @@ -67,7 +74,7 @@ function script.update(dt) local gamepad = ac.getGamepad(0) if not gamepad then - lib.logOnce("gamepad_nil", "[MyGamepadFX] ERROR: No gamepad detected. Check CM → Settings → Assetto Corsa → Controls → Input Method = Gamepad.") + lib.logOnce("gamepad_nil", "[MyGamepadFX] ERROR: No gamepad detected. Check CM \xE2\x86\x92 Settings \xE2\x86\x92 Assetto Corsa \xE2\x86\x92 Controls \xE2\x86\x92 Input Method = Gamepad.") steerOut = 0.0 return end @@ -78,7 +85,6 @@ function script.update(dt) lib.logOnce("frame_drop", "[MyGamepadFX] Warning: frame time " .. string.format("%.0f", dt * 1000) .. "ms exceeds 50ms threshold. Smoothing may be affected.") end - -- First-frame axis diagnostics (once per game start, not per session reset) if not firstFrameDiagnostics then ac.log("[MyGamepadFX] === Startup Diagnostic ===") ac.log("[MyGamepadFX] Axes: [0]=" .. string.format("%.2f", gamepad.axes[0] or 0) @@ -86,60 +92,57 @@ function script.update(dt) .. " [3]=" .. string.format("%.2f", gamepad.axes[3] or 0) .. " [4]=" .. string.format("%.2f", gamepad.axes[4] or 0)) ac.log("[MyGamepadFX] Expected: axes[1]=steer, axes[3]=throttle, axes[4]=brake") + ac.log("[MyGamepadFX] yawRate available: " .. tostring(car.localAngularVelocity ~= nil)) firstFrameDiagnostics = true end - -- 1. Raw input → calibrate → deadzone → gamma → speed scale - local raw = gamepad.axes[1] or 0.0 -- left stick X (steering) + -- 1. Raw input -> calibrate -> deadzone -> gamma -> speed scale + local raw = gamepad.axes[1] or 0.0 local calibrated = lib.normalizeAxis(raw, CFG.STEER_CENTER, CFG.STEER_RANGE) local steer = lib.applyGamma(lib.applyDeadzone(calibrated, CFG.DEADZONE), CFG.GAMMA) steer = steer * lib.speedScale(car.speedKmh, CFG) - -- 2. Slip limit — clamps driver input only; self-steer is added after - local avgFrontSlip = (car.wheelsSlip[0] + car.wheelsSlip[1]) * 0.5 - local slipFactor = math.clamp( - (avgFrontSlip - CFG.SLIP_LIMIT_START) / CFG.SLIP_LIMIT_RANGE, - 0.0, 1.0 - ) + -- 2. Slip classify: front vs rear + local slip = lib.stageSlipClassify(car, CFG) + + -- 3. Slip limit — clamps driver input; tightened by understeer factor + local slipFactor = math.clamp((slip.front - CFG.SLIP_LIMIT_START) / CFG.SLIP_LIMIT_RANGE, 0.0, 1.0) local steerLimit = lib.lerp(1.0, CFG.SLIP_LIMIT_MIN, slipFactor) + steerLimit = steerLimit * lib.lerp(1.0, 1.0 - CFG.US_REDUCTION, slip.understeer) local driverInput = math.clamp(steer, -steerLimit, steerLimit) - -- 3. Self-steer: caster return-to-center + damping (not subject to slip limit) - local selfSteer = -avgFrontSlip * CFG.COUNTERSTEER_GAIN - - car.steer * CFG.COUNTERSTEER_DAMP - local combined = driverInput + selfSteer - - -- 4. Smooth combined signal (driver + self-steer together — avoids correction lag) - steerOut = lib.expSmooth(steerOut, combined, CFG.STEER_SMOOTH, dt) - - -- if dbg and CFG.DEBUG_MODE then dbg.draw({ - -- raw = raw, - -- afterScale = steer, - -- steerLimit = steerLimit, - -- driverInput = driverInput, - -- selfSteer = selfSteer, - -- combined = combined, - -- steerOut = steerOut, - -- avgFrontSlip = avgFrontSlip, - -- speedKmh = car.speedKmh, - -- carSteer = car.steer, - -- dt = dt, - -- }) end - - -- 4.5. Haptic feedback (trigger rumble on front slip) + -- 4. Yaw damping + oversteer boost (replaces self-steer) + local yaw = lib.yawRate(car) + local heavyBraking = (car.brake or 0) > 0.4 and car.speedKmh > 30 + local effectiveDamp = heavyBraking and CFG.YAW_DAMP * 0.6 or CFG.YAW_DAMP + local yawCorrection = lib.stageYawDamp(yaw, car.steer, CFG, slip.oversteer, effectiveDamp) + local combined = driverInput + yawCorrection + + -- 5. Adaptive smooth: faster at the limit, smooth when settled + local avgSlip = (slip.front + slip.rear) * 0.5 + local stability = 1.0 - math.clamp((math.abs(yaw) * 0.5 + avgSlip) / 0.4, 0.0, 1.0) + steerOut = lib.stageAdaptiveSmooth(steerOut, combined, stability, CFG, dt) + + -- 5.5. Haptic feedback if CFG.HAPTICS_ENABLED then local slipIntensity = math.clamp( - (avgFrontSlip - CFG.HAPTICS_SLIP_START) / (CFG.HAPTICS_SLIP_MAX - CFG.HAPTICS_SLIP_START), + (avgSlip - CFG.HAPTICS_SLIP_START) / (CFG.HAPTICS_SLIP_MAX - CFG.HAPTICS_SLIP_START), 0.0, 1.0 ) ac.setTriggerRumble(0, slipIntensity * CFG.HAPTICS_STRENGTH) end - -- 5. Write to physics + -- 6. Write to physics local rawGas = lib.normalizeTrigger(gamepad.axes[3] or 0.0, CFG.GAS_REST, CFG.GAS_MAX) local rawBrake = lib.normalizeTrigger(gamepad.axes[4] or 0.0, CFG.BRAKE_REST, CFG.BRAKE_MAX) + local gasOut = math.clamp(lib.applyGamma(lib.applyDeadzone(rawGas, CFG.GAS_DEADZONE), CFG.GAS_GAMMA), 0.0, 1.0) + if CFG.TC_ENABLED then + local spin = lib.stageWheelspin(car) + local reduction = math.clamp((spin - CFG.TC_SLIP_THRESHOLD) / 0.2, 0.0, 1.0) + gasOut = gasOut * (1.0 - reduction * CFG.TC_MAX_REDUCTION) + end ac.setSteer(math.clamp(steerOut, -1.0, 1.0)) - ac.setGas( math.clamp(lib.applyGamma(lib.applyDeadzone(rawGas, CFG.GAS_DEADZONE), CFG.GAS_GAMMA), 0.0, 1.0)) + ac.setGas(gasOut) ac.setBrake(math.clamp(lib.applyGamma(lib.applyDeadzone(rawBrake, CFG.BRAKE_DEADZONE), CFG.BRAKE_GAMMA), 0.0, 1.0)) end diff --git a/MyGamepadFX/config.lua b/MyGamepadFX/config.lua index c11dcfd..199dd9b 100644 --- a/MyGamepadFX/config.lua +++ b/MyGamepadFX/config.lua @@ -1,7 +1,7 @@ -- config.lua — all tunable constants; no logic lives here local CFG = { -- Axis calibration (Hall Effect controllers) - -- Defaults produce no change from v1.0 behaviour. + -- Defaults produce no change from pre-calibration behaviour. STEER_CENTER = 0.0, -- raw stick value at rest; subtracted before deadzone STEER_RANGE = 1.0, -- max raw deflection from center (scale to ±1.0) GAS_REST = 0.0, -- raw trigger value when fully released @@ -14,16 +14,22 @@ local CFG = { GAMMA = 1.6, -- steering curve exponent (>1 = more center precision) -- Smoothing - STEER_SMOOTH = 0.12, -- blend weight at 60 fps (frame-rate independent) + STEER_SMOOTH = 0.12, -- stable-state blend weight at 60 fps + STEER_SMOOTH_MIN = 0.04, -- minimum blend weight at high instability (v2.0) -- Speed scaling SPEED_SCALE_START = 60, -- km/h where speed scaling begins SPEED_SCALE_END = 180, -- km/h where scaling reaches minimum SPEED_SCALE_MIN = 0.35, -- minimum steering multiplier at top speed - -- Self-steer - COUNTERSTEER_GAIN = 0.45, -- correction strength - COUNTERSTEER_DAMP = 0.30, -- oscillation damping; must stay >= (COUNTERSTEER_GAIN * 0.6) + -- Yaw damping (v2.0 — replaces COUNTERSTEER_GAIN/DAMP) + YAW_GAIN = 0.5, -- countersteer force per rad/s of yaw + YAW_DAMP = 0.3, -- steer angle damping when yawing + + -- Slip discrimination (v2.0) + SLIP_DELTA_THRESH = 0.08, -- front-rear slip difference that fully classifies under/oversteer + US_REDUCTION = 0.25, -- max authority reduction when understeering (0 = disabled) + OS_BOOST = 0.3, -- max countersteer boost when oversteering (0 = disabled) -- Slip limit SLIP_LIMIT_START = 0.15, -- front slip level where reduction begins @@ -36,14 +42,19 @@ local CFG = { BRAKE_DEADZONE = 0.01, -- avoids light brake from trigger drift BRAKE_GAMMA = 1.0, -- linear brake (no curve) + -- Traction control (v2.0, off by default) + TC_ENABLED = false, -- enable to reduce wheelspin automatically + TC_SLIP_THRESHOLD = 0.15, -- rear wheelspin ratio where TC activates + TC_MAX_REDUCTION = 0.5, -- maximum throttle reduction fraction + -- Haptic feedback (trigger rumble, CSP v0.2.0+) - HAPTICS_ENABLED = false, -- disabled by default; enable in config if controller supports it - HAPTICS_SLIP_START = 0.3, -- front slip level where rumble begins - HAPTICS_SLIP_MAX = 1.0, -- slip level for maximum rumble - HAPTICS_STRENGTH = 0.8, -- overall rumble intensity [0, 1] + HAPTICS_ENABLED = false, + HAPTICS_SLIP_START = 0.3, + HAPTICS_SLIP_MAX = 1.0, + HAPTICS_STRENGTH = 0.8, -- Debug / tuning mode - DEBUG_MODE = false, -- set true to enable live telemetry overlay + DEBUG_MODE = false, } return CFG diff --git a/MyGamepadFX/lib.lua b/MyGamepadFX/lib.lua index 89e8f23..35eb523 100644 --- a/MyGamepadFX/lib.lua +++ b/MyGamepadFX/lib.lua @@ -1,4 +1,4 @@ --- lib.lua — math primitives; no constants, no ac.* API calls +-- lib.lua — math primitives and pipeline stage functions; no constants, no ac.* API calls -- Note: math.clamp is a CSP extension, not available in vanilla LuaJIT. local M = {} @@ -64,4 +64,49 @@ function M.speedScale(speedKmh, cfg) return M.lerp(1.0, cfg.SPEED_SCALE_MIN, t) end +-- Yaw rate from car object. Returns 0.0 if unavailable (pre-v2.0 CSP). +-- car.localAngularVelocity is body-frame rad/s; .y = yaw (positive = rotating left). +function M.yawRate(car) + if not car.localAngularVelocity then return 0.0 end + return car.localAngularVelocity.y +end + +-- Classify front vs rear slip to determine oversteer/understeer state. +-- Returns { front, rear, understeer, oversteer } all in [0, 1]. +function M.stageSlipClassify(car, cfg) + local front = (car.wheelsSlip[0] + car.wheelsSlip[1]) * 0.5 + local rear = (car.wheelsSlip[2] + car.wheelsSlip[3]) * 0.5 + local delta = front - rear -- positive = understeer, negative = oversteer + local thresh = cfg.SLIP_DELTA_THRESH + return { + front = front, + rear = rear, + understeer = math.clamp( delta / thresh, 0.0, 1.0), + oversteer = math.clamp(-delta / thresh, 0.0, 1.0), + } +end + +-- Yaw damping: opposes car rotation and steer angle oscillation. +-- overFactor scales yaw correction up when oversteering; effectiveDamp handles load transfer. +function M.stageYawDamp(yaw, steerAngle, cfg, overFactor, effectiveDamp) + local yawPart = -yaw * cfg.YAW_GAIN * M.lerp(1.0, 1.0 + cfg.OS_BOOST, overFactor) + local dampPart = -steerAngle * effectiveDamp + return yawPart + dampPart +end + +-- Adaptive smooth: faster at the limit, stable when settled. +-- stability in [0, 1] where 1 = fully stable. +function M.stageAdaptiveSmooth(current, target, stability, cfg, dt) + local smooth = M.lerp(cfg.STEER_SMOOTH_MIN, cfg.STEER_SMOOTH, stability) + return M.expSmooth(current, target, smooth, dt) +end + +-- Rear wheelspin ratio. Returns value in [0, 1] where 0 = no spin, 1 = full spin. +function M.stageWheelspin(car) + local expected = car.speedKmh / 3.6 / 0.3 -- ~0.3m typical tyre radius + if expected < 1.0 then return 0.0 end + local rearAvg = (car.wheelAngularSpeed[2] + car.wheelAngularSpeed[3]) * 0.5 + return math.clamp(rearAvg / expected - 1.0, 0.0, 1.0) +end + return M diff --git a/MyGamepadFX/manifest.ini b/MyGamepadFX/manifest.ini index 7cd90d0..8a44d3f 100644 --- a/MyGamepadFX/manifest.ini +++ b/MyGamepadFX/manifest.ini @@ -1,3 +1,3 @@ [ABOUT] NAME = MyGamepadFX -VERSION = 1.0 +VERSION = 2.0 diff --git a/MyGamepadFX_Config/app.lua b/MyGamepadFX_Config/app.lua index 1afdf1d..4134f83 100644 --- a/MyGamepadFX_Config/app.lua +++ b/MyGamepadFX_Config/app.lua @@ -21,11 +21,15 @@ local cfg = { DEADZONE = 0.08, GAMMA = 1.6, STEER_SMOOTH = 0.12, + STEER_SMOOTH_MIN = 0.04, SPEED_SCALE_START = 60, SPEED_SCALE_END = 180, SPEED_SCALE_MIN = 0.35, - COUNTERSTEER_GAIN = 0.45, - COUNTERSTEER_DAMP = 0.30, + YAW_GAIN = 0.5, + YAW_DAMP = 0.3, + SLIP_DELTA_THRESH = 0.08, + US_REDUCTION = 0.25, + OS_BOOST = 0.3, SLIP_LIMIT_START = 0.15, SLIP_LIMIT_RANGE = 0.25, SLIP_LIMIT_MIN = 0.70, @@ -33,6 +37,9 @@ local cfg = { GAS_GAMMA = 1.1, BRAKE_DEADZONE = 0.01, BRAKE_GAMMA = 1.0, + TC_ENABLED = false, + TC_SLIP_THRESHOLD = 0.15, + TC_MAX_REDUCTION = 0.5, HAPTICS_ENABLED = false, HAPTICS_SLIP_START = 0.3, HAPTICS_SLIP_MAX = 1.0, @@ -55,11 +62,15 @@ local function saveLiveCfg() ini:set('PARAMS', 'DEADZONE', cfg.DEADZONE) ini:set('PARAMS', 'GAMMA', cfg.GAMMA) ini:set('PARAMS', 'STEER_SMOOTH', cfg.STEER_SMOOTH) + ini:set('PARAMS', 'STEER_SMOOTH_MIN', cfg.STEER_SMOOTH_MIN) ini:set('PARAMS', 'SPEED_SCALE_START', cfg.SPEED_SCALE_START) ini:set('PARAMS', 'SPEED_SCALE_END', cfg.SPEED_SCALE_END) ini:set('PARAMS', 'SPEED_SCALE_MIN', cfg.SPEED_SCALE_MIN) - ini:set('PARAMS', 'COUNTERSTEER_GAIN', cfg.COUNTERSTEER_GAIN) - ini:set('PARAMS', 'COUNTERSTEER_DAMP', cfg.COUNTERSTEER_DAMP) + ini:set('PARAMS', 'YAW_GAIN', cfg.YAW_GAIN) + ini:set('PARAMS', 'YAW_DAMP', cfg.YAW_DAMP) + ini:set('PARAMS', 'SLIP_DELTA_THRESH', cfg.SLIP_DELTA_THRESH) + ini:set('PARAMS', 'US_REDUCTION', cfg.US_REDUCTION) + ini:set('PARAMS', 'OS_BOOST', cfg.OS_BOOST) ini:set('PARAMS', 'SLIP_LIMIT_START', cfg.SLIP_LIMIT_START) ini:set('PARAMS', 'SLIP_LIMIT_RANGE', cfg.SLIP_LIMIT_RANGE) ini:set('PARAMS', 'SLIP_LIMIT_MIN', cfg.SLIP_LIMIT_MIN) @@ -67,6 +78,9 @@ local function saveLiveCfg() ini:set('PARAMS', 'GAS_GAMMA', cfg.GAS_GAMMA) ini:set('PARAMS', 'BRAKE_DEADZONE', cfg.BRAKE_DEADZONE) ini:set('PARAMS', 'BRAKE_GAMMA', cfg.BRAKE_GAMMA) + ini:set('PARAMS', 'TC_ENABLED', cfg.TC_ENABLED) + ini:set('PARAMS', 'TC_SLIP_THRESHOLD', cfg.TC_SLIP_THRESHOLD) + ini:set('PARAMS', 'TC_MAX_REDUCTION', cfg.TC_MAX_REDUCTION) ini:set('PARAMS', 'HAPTICS_ENABLED', cfg.HAPTICS_ENABLED) ini:set('PARAMS', 'HAPTICS_SLIP_START', cfg.HAPTICS_SLIP_START) ini:set('PARAMS', 'HAPTICS_SLIP_MAX', cfg.HAPTICS_SLIP_MAX) @@ -91,11 +105,15 @@ local function loadSaved() cfg.DEADZONE = ini:get('PARAMS', 'DEADZONE', cfg.DEADZONE) cfg.GAMMA = ini:get('PARAMS', 'GAMMA', cfg.GAMMA) cfg.STEER_SMOOTH = ini:get('PARAMS', 'STEER_SMOOTH', cfg.STEER_SMOOTH) + cfg.STEER_SMOOTH_MIN = ini:get('PARAMS', 'STEER_SMOOTH_MIN', cfg.STEER_SMOOTH_MIN) cfg.SPEED_SCALE_START = ini:get('PARAMS', 'SPEED_SCALE_START', cfg.SPEED_SCALE_START) cfg.SPEED_SCALE_END = ini:get('PARAMS', 'SPEED_SCALE_END', cfg.SPEED_SCALE_END) cfg.SPEED_SCALE_MIN = ini:get('PARAMS', 'SPEED_SCALE_MIN', cfg.SPEED_SCALE_MIN) - cfg.COUNTERSTEER_GAIN = ini:get('PARAMS', 'COUNTERSTEER_GAIN', cfg.COUNTERSTEER_GAIN) - cfg.COUNTERSTEER_DAMP = ini:get('PARAMS', 'COUNTERSTEER_DAMP', cfg.COUNTERSTEER_DAMP) + cfg.YAW_GAIN = ini:get('PARAMS', 'YAW_GAIN', cfg.YAW_GAIN) + cfg.YAW_DAMP = ini:get('PARAMS', 'YAW_DAMP', cfg.YAW_DAMP) + cfg.SLIP_DELTA_THRESH = ini:get('PARAMS', 'SLIP_DELTA_THRESH', cfg.SLIP_DELTA_THRESH) + cfg.US_REDUCTION = ini:get('PARAMS', 'US_REDUCTION', cfg.US_REDUCTION) + cfg.OS_BOOST = ini:get('PARAMS', 'OS_BOOST', cfg.OS_BOOST) cfg.SLIP_LIMIT_START = ini:get('PARAMS', 'SLIP_LIMIT_START', cfg.SLIP_LIMIT_START) cfg.SLIP_LIMIT_RANGE = ini:get('PARAMS', 'SLIP_LIMIT_RANGE', cfg.SLIP_LIMIT_RANGE) cfg.SLIP_LIMIT_MIN = ini:get('PARAMS', 'SLIP_LIMIT_MIN', cfg.SLIP_LIMIT_MIN) @@ -103,6 +121,9 @@ local function loadSaved() cfg.GAS_GAMMA = ini:get('PARAMS', 'GAS_GAMMA', cfg.GAS_GAMMA) cfg.BRAKE_DEADZONE = ini:get('PARAMS', 'BRAKE_DEADZONE', cfg.BRAKE_DEADZONE) cfg.BRAKE_GAMMA = ini:get('PARAMS', 'BRAKE_GAMMA', cfg.BRAKE_GAMMA) + cfg.TC_ENABLED = ini:get('PARAMS', 'TC_ENABLED', cfg.TC_ENABLED) + cfg.TC_SLIP_THRESHOLD = ini:get('PARAMS', 'TC_SLIP_THRESHOLD', cfg.TC_SLIP_THRESHOLD) + cfg.TC_MAX_REDUCTION = ini:get('PARAMS', 'TC_MAX_REDUCTION', cfg.TC_MAX_REDUCTION) cfg.HAPTICS_ENABLED = ini:get('PARAMS', 'HAPTICS_ENABLED', cfg.HAPTICS_ENABLED) cfg.HAPTICS_SLIP_START = ini:get('PARAMS', 'HAPTICS_SLIP_START', cfg.HAPTICS_SLIP_START) cfg.HAPTICS_SLIP_MAX = ini:get('PARAMS', 'HAPTICS_SLIP_MAX', cfg.HAPTICS_SLIP_MAX) @@ -142,9 +163,10 @@ function windowMain(dt) ui.offsetCursorY(8) ui.text('Steering') ui.separator() - sliderRow('Deadzone', 'DEADZONE', 0.0, 0.30, '%.2f') - sliderRow('Gamma', 'GAMMA', 1.0, 3.0, '%.2f') - sliderRow('Smooth', 'STEER_SMOOTH', 0.01, 0.50, '%.2f') + sliderRow('Deadzone', 'DEADZONE', 0.0, 0.30, '%.2f') + sliderRow('Gamma', 'GAMMA', 1.0, 3.0, '%.2f') + sliderRow('Smooth', 'STEER_SMOOTH', 0.01, 0.50, '%.2f') + sliderRow('Smooth min', 'STEER_SMOOTH_MIN', 0.01, 0.20, '%.2f') ui.offsetCursorY(8) ui.text('Speed Scaling') @@ -154,10 +176,13 @@ function windowMain(dt) sliderRow('Min scale', 'SPEED_SCALE_MIN', 0.1, 1.0, '%.2f') ui.offsetCursorY(8) - ui.text('Self-Steer') + ui.text('Dynamics') ui.separator() - sliderRow('Gain', 'COUNTERSTEER_GAIN', 0.0, 1.0, '%.2f') - sliderRow('Damp', 'COUNTERSTEER_DAMP', 0.0, 1.0, '%.2f') + sliderRow('Yaw gain', 'YAW_GAIN', 0.0, 1.5, '%.2f') + sliderRow('Yaw damp', 'YAW_DAMP', 0.0, 1.0, '%.2f') + sliderRow('Slip thresh', 'SLIP_DELTA_THRESH', 0.01, 0.30, '%.2f') + sliderRow('US reduce', 'US_REDUCTION', 0.0, 1.0, '%.2f') + sliderRow('OS boost', 'OS_BOOST', 0.0, 1.0, '%.2f') ui.offsetCursorY(8) ui.text('Slip Limit') @@ -174,6 +199,18 @@ function windowMain(dt) sliderRow('Brake dz', 'BRAKE_DEADZONE', 0.0, 0.10, '%.3f') sliderRow('Brake gamma', 'BRAKE_GAMMA', 0.5, 2.0, '%.2f') + ui.offsetCursorY(8) + ui.text('Traction Control') + ui.separator() + if ui.checkbox('Enabled##tc', cfg.TC_ENABLED) then + cfg.TC_ENABLED = not cfg.TC_ENABLED + dirty = true + end + if cfg.TC_ENABLED then + sliderRow('Slip thresh', 'TC_SLIP_THRESHOLD', 0.05, 0.5, '%.2f') + sliderRow('Max reduction', 'TC_MAX_REDUCTION', 0.1, 1.0, '%.2f') + end + ui.offsetCursorY(8) ui.text('Haptics') ui.separator() diff --git a/MyGamepadFX_Config/manifest.ini b/MyGamepadFX_Config/manifest.ini index 7f453ad..6b1ac4e 100644 --- a/MyGamepadFX_Config/manifest.ini +++ b/MyGamepadFX_Config/manifest.ini @@ -1,10 +1,10 @@ [ABOUT] NAME = MyGamepadFX Config AUTHOR = rolling-codes -VERSION = 1.1 +VERSION = 2.0 [CORE] LAZY = FULL [WINDOW_MAIN] ID = main FUNCTION_MAIN = windowMain -SIZE = 380, 800 +SIZE = 380, 960