local input = require('openmw.input') local util = require('openmw.util') local async = require('openmw.async') local storage = require('openmw.storage') local types = require('openmw.types') local self = require('openmw.self') local NPC = types.NPC local moveActions = { 'MoveForward', 'MoveBackward', 'MoveLeft', 'MoveRight' } for _, key in ipairs(moveActions) do local smoothKey = 'Smooth' .. key input.registerAction { key = smoothKey, l10n = 'OMWControls', name = smoothKey .. '_name', description = smoothKey .. '_description', type = input.ACTION_TYPE.Range, defaultValue = 0, } end local settings = storage.playerSection('SettingsOMWControls') local function shouldAlwaysRun(actor) return actor.controls.sneak or not NPC.isOnGround(actor) or NPC.isSwimming(actor) end local function remapToWalkRun(actor, inputMovement) if shouldAlwaysRun(actor) then return true, inputMovement end local normalizedInput, inputSpeed = inputMovement:normalize() local switchPoint = 0.5 if inputSpeed < switchPoint then return false, inputMovement * 2 else local matchWalkingSpeed = NPC.getWalkSpeed(actor) / NPC.getRunSpeed(actor) local runSpeedRatio = 2 * (inputSpeed - switchPoint) * (1 - matchWalkingSpeed) + matchWalkingSpeed return true, normalizedInput * math.min(1, runSpeedRatio) end end local function computeSmoothMovement() local controllerInput = util.vector2( input.getAxisValue(input.CONTROLLER_AXIS.MoveForwardBackward), input.getAxisValue(input.CONTROLLER_AXIS.MoveLeftRight) ) return remapToWalkRun(self, controllerInput) end local function bindSmoothMove(key, axis, direction) local smoothKey = 'Smooth' .. key input.bindAction(smoothKey, async:callback(function() local _, movement = computeSmoothMovement() return math.max(direction * movement[axis], 0) end), {}) input.bindAction(key, async:callback(function(_, standardMovement, smoothMovement) if not settings:get('smoothControllerMovement') then return standardMovement end if smoothMovement > 0 then return smoothMovement else return standardMovement end end), { smoothKey }) end bindSmoothMove('MoveForward', 'x', -1) bindSmoothMove('MoveBackward', 'x', 1) bindSmoothMove('MoveRight', 'y', 1) bindSmoothMove('MoveLeft', 'y', -1) input.bindAction('Run', async:callback(function(_, run) if not settings:get('smoothControllerMovement') then return run end local smoothRun, movement = computeSmoothMovement() if movement:length2() > 0 then -- ignore always run return smoothRun ~= settings:get('alwaysRun') else return run end end), {})