Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282local core = require('openmw.core')local debug = require('openmw.debug')local input = require('openmw.input')local self = require('openmw.self')local storage = require('openmw.storage')local ui = require('openmw.ui')local async = require('openmw.async')local Actor = require('openmw.types').Actorlocal Player = require('openmw.types').Player
local I = require('openmw.interfaces')
local settings = storage.playerSection('SettingsOMWControls')
do local rangeActions = { 'MoveForward', 'MoveBackward', 'MoveLeft', 'MoveRight' } for _, key in ipairs(rangeActions) do input.registerAction { key = key, l10n = 'OMWControls', name = key .. '_name', description = key .. '_description', type = input.ACTION_TYPE.Range, defaultValue = 0, } end
local booleanActions = { 'Use', 'Run', 'Sneak', } for _, key in ipairs(booleanActions) do input.registerAction { key = key, l10n = 'OMWControls', name = key .. '_name', description = key .. '_description', type = input.ACTION_TYPE.Boolean, defaultValue = false, } end
local triggers = { 'Jump', 'AutoMove', 'ToggleWeapon', 'ToggleSpell', 'AlwaysRun', 'ToggleSneak', 'Inventory', 'Journal', 'QuickKeysMenu', } for _, key in ipairs(triggers) do input.registerTrigger { key = key, l10n = 'OMWControls', name = key .. '_name', description = key .. '_description', } endend
local function checkNotWerewolf() if Player.isWerewolf(self) then ui.showMessage(core.getGMST('sWerewolfRefusal')) return false else return true endend
local function isJournalAllowed() -- During chargen journal is not allowed until magic window is allowed return I.UI.getWindowsForMode(I.UI.MODE.Interface)[I.UI.WINDOW.Magic]end
local movementControlsOverridden = false
local autoMove = falselocal attemptToJump = falselocal function processMovement() local movement = input.getRangeActionValue('MoveForward') - input.getRangeActionValue('MoveBackward') local sideMovement = input.getRangeActionValue('MoveRight') - input.getRangeActionValue('MoveLeft') local run = input.getBooleanActionValue('Run') ~= settings:get('alwaysRun')
if movement ~= 0 then autoMove = false elseif autoMove then movement = 1 end
self.controls.movement = movement self.controls.sideMovement = sideMovement self.controls.run = run self.controls.jump = attemptToJump
if not settings:get('toggleSneak') then self.controls.sneak = input.getBooleanActionValue('Sneak') endend
local function controlsAllowed() if core.isWorldPaused() then return false end if not Player.getControlSwitch(self, Player.CONTROL_SWITCH.Controls) then return false end if I.UI.getMode() then return false end if debug.isGodMode() then return true end local paralysis = Actor.activeEffects(self):getEffect(core.magic.EFFECT_TYPE.Paralyze) return paralysis.magnitude <= 0end
local function movementAllowed() return controlsAllowed() and not movementControlsOverriddenend
input.registerTriggerHandler('Jump', async:callback(function() if not movementAllowed() then return end attemptToJump = Player.getControlSwitch(self, Player.CONTROL_SWITCH.Jumping)end))
input.registerTriggerHandler('ToggleSneak', async:callback(function() if not movementAllowed() then return end if settings:get('toggleSneak') then self.controls.sneak = not self.controls.sneak endend))
input.registerTriggerHandler('AlwaysRun', async:callback(function() if not movementAllowed() then return end settings:set('alwaysRun', not settings:get('alwaysRun'))end))
input.registerTriggerHandler('AutoMove', async:callback(function() if not movementAllowed() then return end autoMove = not autoMoveend))
local combatControlsOverridden = false
local function combatAllowed() return controlsAllowed() and not combatControlsOverriddenend
input.registerTriggerHandler('ToggleSpell', async:callback(function() if not combatAllowed() then return end if Actor.getStance(self) == Actor.STANCE.Spell then Actor.setStance(self, Actor.STANCE.Nothing) elseif Player.getControlSwitch(self, Player.CONTROL_SWITCH.Magic) then if checkNotWerewolf() then Actor.setStance(self, Actor.STANCE.Spell) end endend))
input.registerTriggerHandler('ToggleWeapon', async:callback(function() if not combatAllowed() then return end if Actor.getStance(self) == Actor.STANCE.Weapon then Actor.setStance(self, Actor.STANCE.Nothing) elseif Player.getControlSwitch(self, Player.CONTROL_SWITCH.Fighting) then Actor.setStance(self, Actor.STANCE.Weapon) endend))
local startUse = falseinput.registerActionHandler('Use', async:callback(function(value) if value and combatAllowed() then startUse = true endend))local function processAttacking() -- for spell-casting, set controls.use to true for exactly one frame -- otherwise spell casting is attempted every frame while Use is true if Actor.getStance(self) == Actor.STANCE.Spell then self.controls.use = startUse and self.ATTACK_TYPE.Any or self.ATTACK_TYPE.NoAttack elseif Actor.getStance(self) == Actor.STANCE.Weapon and input.getBooleanActionValue('Use') then self.controls.use = self.ATTACK_TYPE.Any else self.controls.use = self.ATTACK_TYPE.NoAttack end startUse = falseend
local uiControlsOverridden = false
local function uiAllowed() return Player.getControlSwitch(self, Player.CONTROL_SWITCH.Controls) and not uiControlsOverriddenend
input.registerTriggerHandler('Inventory', async:callback(function() if not uiAllowed() then return end
if I.UI.getMode() == nil then I.UI.setMode(I.UI.MODE.Interface) elseif I.UI.getMode() == I.UI.MODE.Interface or I.UI.getMode() == I.UI.MODE.Container then I.UI.removeMode(I.UI.getMode()) endend))
input.registerTriggerHandler('Journal', async:callback(function() if not uiAllowed() then return end
if I.UI.getMode() == I.UI.MODE.Journal then I.UI.removeMode(I.UI.MODE.Journal) elseif isJournalAllowed() then I.UI.addMode(I.UI.MODE.Journal) endend))
input.registerTriggerHandler('QuickKeysMenu', async:callback(function() if not uiAllowed() then return end
if I.UI.getMode() == I.UI.MODE.QuickKeysMenu then I.UI.removeMode(I.UI.MODE.QuickKeysMenu) elseif checkNotWerewolf() and Player.isCharGenFinished(self) then I.UI.addMode(I.UI.MODE.QuickKeysMenu) endend))
local function onFrame(_) if movementAllowed() then processMovement() elseif not movementControlsOverridden then self.controls.movement = 0 self.controls.sideMovement = 0 self.controls.jump = false end if combatAllowed() then processAttacking() end attemptToJump = falseend
local function onSave() return { sneaking = self.controls.sneak }end
local function onLoad(data) if not data then return end self.controls.sneak = data.sneaking or falseend
return { engineHandlers = { onFrame = onFrame, onSave = onSave, onLoad = onLoad, }, interfaceName = 'Controls', --- -- @module Controls -- @context player -- @usage require('openmw.interfaces').Controls interface = { --- Interface version -- @field [parent=#Controls] #number version version = 1,
--- When set to true then the movement controls including jump and sneak are not processed and can be handled by another script. -- If movement should be disallowed completely, consider to use `types.Player.setControlSwitch` instead. -- @function [parent=#Controls] overrideMovementControls -- @param #boolean value overrideMovementControls = function(v) movementControlsOverridden = v end,
--- When set to true then the controls "attack", "toggle spell", "toggle weapon" are not processed and can be handled by another script. -- If combat should be disallowed completely, consider to use `types.Player.setControlSwitch` instead. -- @function [parent=#Controls] overrideCombatControls -- @param #boolean value overrideCombatControls = function(v) combatControlsOverridden = v end,
--- When set to true then the controls "open inventory", "open journal" and so on are not processed and can be handled by another script. -- @function [parent=#Controls] overrideUiControls -- @param #boolean value overrideUiControls = function(v) uiControlsOverridden = v end, }}