Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262local input = require('openmw.input')local util = require('openmw.util')local async = require('openmw.async')local storage = require('openmw.storage')
local actionPressHandlers = {}local function onActionPress(id, handler) actionPressHandlers[id] = actionPressHandlers[id] or {} table.insert(actionPressHandlers[id], handler)end
local function bindHold(key, actionId) input.bindAction(key, async:callback(function() return input.isActionPressed(actionId) end), {})end
local function bindMovement(key, actionId, axisId, direction) input.bindAction(key, async:callback(function() local actionActive = input.isActionPressed(actionId) local axisActive = input.getAxisValue(axisId) * direction > 0 return (actionActive or axisActive) and 1 or 0 end), {})end
local function bindTrigger(key, actionid) onActionPress(actionid, function() input.activateTrigger(key) end)end
do -- Actions and Triggers currently unused by builtin scripts -- TODO: as more mechanics are dehardcoded, move these declarations to relevant files local triggers = { Activate = input.ACTION.Activate, Console = input.ACTION.Console, CycleSpellLeft = input.ACTION.CycleSpellLeft, CycleSpellRight = input.ACTION.CycleSpellRight, CycleWeaponLeft = input.ACTION.CycleWeaponLeft, CycleWeaponRight = input.ACTION.CycleWeaponRight, GameMenu = input.ACTION.GameMenu, QuickLoad = input.ACTION.QuickLoad, QuickSave = input.ACTION.QuickSave, Screenshot = input.ACTION.Screenshot, ToggleDebug = input.ACTION.ToggleDebug, ToggleHUD = input.ACTION.ToggleHUD, TogglePostProcessorHUD = input.ACTION.ToggleHUD, } for i = 1, 9 do local key = string.format('QuickKey%s', i) triggers[key] = input.ACTION[key] end for key, action in pairs(triggers) do input.registerTrigger { key = key, l10n = 'OMWControls', name = key .. '_name', description = key .. '_description', } bindTrigger(key, action) endend
bindTrigger('AlwaysRun', input.ACTION.AlwaysRun)bindTrigger('ToggleSneak', input.ACTION.Sneak)bindTrigger('ToggleWeapon', input.ACTION.ToggleWeapon)bindTrigger('ToggleSpell', input.ACTION.ToggleSpell)bindTrigger('Jump', input.ACTION.Jump)bindTrigger('AutoMove', input.ACTION.AutoMove)bindTrigger('Inventory', input.ACTION.Inventory)bindTrigger('Journal', input.ACTION.Journal)bindTrigger('QuickKeysMenu', input.ACTION.QuickKeysMenu)
bindHold('TogglePOV', input.ACTION.TogglePOV)bindHold('Sneak', input.ACTION.Sneak)
bindHold('Run', input.ACTION.Run)input.bindAction('Run', async:callback(function(_, value) local controllerInput = util.vector2( input.getAxisValue(input.CONTROLLER_AXIS.MoveForwardBackward), input.getAxisValue(input.CONTROLLER_AXIS.MoveLeftRight) ):length2() return value or controllerInput > 0.25end), {})
input.bindAction('Use', async:callback(function() -- The value "0.6" shouldn't exceed the triggering threshold in BindingsManager::actionValueChanged. -- TODO: Move more logic from BindingsManager to Lua and consider to make this threshold configurable. return input.isActionPressed(input.ACTION.Use) or input.getAxisValue(input.CONTROLLER_AXIS.TriggerRight) >= 0.6end), {})
bindMovement('MoveBackward', input.ACTION.MoveBackward, input.CONTROLLER_AXIS.MoveForwardBackward, 1)bindMovement('MoveForward', input.ACTION.MoveForward, input.CONTROLLER_AXIS.MoveForwardBackward, -1)bindMovement('MoveRight', input.ACTION.MoveRight, input.CONTROLLER_AXIS.MoveLeftRight, 1)bindMovement('MoveLeft', input.ACTION.MoveLeft, input.CONTROLLER_AXIS.MoveLeftRight, -1)
do local zoomInOut = 0 onActionPress(input.ACTION.ZoomIn, function() zoomInOut = zoomInOut + 1 end) onActionPress(input.ACTION.ZoomOut, function() zoomInOut = zoomInOut - 1 end) input.bindAction('Zoom3rdPerson', async:callback(function(dt, _, togglePOV) local Zoom3rdPerson = zoomInOut * 10 if togglePOV then local triggerLeft = input.getAxisValue(input.CONTROLLER_AXIS.TriggerLeft) local triggerRight = input.getAxisValue(input.CONTROLLER_AXIS.TriggerRight) local controllerZoom = (triggerRight - triggerLeft) * 100 * dt Zoom3rdPerson = Zoom3rdPerson + controllerZoom end zoomInOut = 0 return Zoom3rdPerson end), { 'TogglePOV' })end
local bindingSection = storage.playerSection('OMWInputBindings')
local devices = { keyboard = true, mouse = true, controller = true}
local function invalidBinding(binding) if not binding.key then return 'has no key' elseif binding.type ~= 'action' and binding.type ~= 'trigger' then return string.format('has invalid type', binding.type) elseif binding.type == 'action' and not input.actions[binding.key] then return string.format("action %s doesn't exist", binding.key) elseif binding.type == 'trigger' and not input.triggers[binding.key] then return string.format("trigger %s doesn't exist", binding.key) elseif not binding.device or not devices[binding.device] then return string.format("invalid device %s", binding.device) elseif not binding.button then return 'has no button' endend
local boundActions = {}local actionBindings = {}
local function bindAction(binding, id) local action = binding.key actionBindings[action] = actionBindings[action] or {} actionBindings[action][id] = binding if not boundActions[action] then boundActions[binding.key] = true input.bindAction(action, async:callback(function() for _, binding in pairs(actionBindings[action] or {}) do if binding.device == 'keyboard' then if input.isKeyPressed(binding.button) then return true end elseif binding.device == 'mouse' then if input.isMouseButtonPressed(binding.button) then return true end elseif binding.device == 'controller' then if input.isControllerButtonPressed(binding.button) then return true end end end return false end), {}) endend
local triggerBindings = {}for device in pairs(devices) do triggerBindings[device] = {} end
local function bindTrigger(binding, id) local deviceBindings = triggerBindings[binding.device] deviceBindings[binding.button] = deviceBindings[binding.button] or {} deviceBindings[binding.button][id] = bindingend
local function registerBinding(binding, id) local invalid = invalidBinding(binding) if invalid then print(string.format('Skipping invalid binding %s: %s', id, invalid)) elseif binding.type == 'action' then bindAction(binding, id) elseif binding.type == 'trigger' then bindTrigger(binding, id) endend
function clearBinding(id) for _, deviceBindings in pairs(triggerBindings) do for _, buttonBindings in pairs(deviceBindings) do buttonBindings[id] = nil end end
for _, bindings in pairs(actionBindings) do bindings[id] = nil endend
bindingSection:subscribe(async:callback(function(_, id) if not id then return end local binding = bindingSection:get(id) clearBinding(id) if binding ~= nil then registerBinding(binding, id) end return idend))
local initiated = false
local function init() for id, binding in pairs(bindingSection:asTable()) do registerBinding(binding, id) endend
return { engineHandlers = { onFrame = function() if not initiated then initiated = true init() end end, onInputAction = function(id) if not actionPressHandlers[id] then return end for _, handler in ipairs(actionPressHandlers[id]) do handler() end end, onKeyPress = function(e) local buttonTriggers = triggerBindings.keyboard[e.code] if not buttonTriggers then return end for _, binding in pairs(buttonTriggers) do input.activateTrigger(binding.key) end end, onMouseButtonPress = function(button) local buttonTriggers = triggerBindings.mouse[button] if not buttonTriggers then return end for _, binding in pairs(buttonTriggers) do input.activateTrigger(binding.key) end end, onControllerButtonPress = function(id) local buttonTriggers = triggerBindings.controller[id] if not buttonTriggers then return end for _, binding in pairs(buttonTriggers) do input.activateTrigger(binding.key) end end, }}