diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d59e87344..ba0cd672cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,7 +71,7 @@ message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MINOR 49) set(OPENMW_VERSION_RELEASE 0) -set(OPENMW_LUA_API_REVISION 49) +set(OPENMW_LUA_API_REVISION 50) set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_TAGHASH "") diff --git a/apps/openmw/mwlua/inputbindings.cpp b/apps/openmw/mwlua/inputbindings.cpp index 9384eccdbc..02babf0399 100644 --- a/apps/openmw/mwlua/inputbindings.cpp +++ b/apps/openmw/mwlua/inputbindings.cpp @@ -77,6 +77,7 @@ namespace MWLua return input->getActionValue(axis - SDL_CONTROLLER_AXIS_MAX) * 2 - 1; }; + // input.CONTROL_SWITCH is deprecated, remove after releasing 0.49 api["getControlSwitch"] = [input](std::string_view key) { return input->getControlSwitch(key); }; api["setControlSwitch"] = [input](std::string_view key, bool v) { input->toggleControlSwitch(key, v); }; @@ -134,6 +135,7 @@ namespace MWLua { "ZoomOut", MWInput::A_ZoomOut }, })); + // input.CONTROL_SWITCH is deprecated, remove after releasing 0.49 api["CONTROL_SWITCH"] = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs({ { "Controls", "playercontrols" }, diff --git a/apps/openmw/mwlua/types/player.cpp b/apps/openmw/mwlua/types/player.cpp index c0eb61bfc7..ab15385f08 100644 --- a/apps/openmw/mwlua/types/player.cpp +++ b/apps/openmw/mwlua/types/player.cpp @@ -1,6 +1,7 @@ #include "types.hpp" #include "../luamanagerimp.hpp" +#include #include #include #include @@ -119,6 +120,31 @@ namespace MWLua }, "addJournalEntryAction"); }; + + player["CONTROL_SWITCH"] + = LuaUtil::makeStrictReadOnly(context.mLua->tableFromPairs({ + { "Controls", "playercontrols" }, + { "Fighting", "playerfighting" }, + { "Jumping", "playerjumping" }, + { "Looking", "playerlooking" }, + { "Magic", "playermagic" }, + { "ViewMode", "playerviewswitch" }, + { "VanityMode", "vanitymode" }, + })); + + MWBase::InputManager* input = MWBase::Environment::get().getInputManager(); + player["getControlSwitch"] = [input](const Object& player, std::string_view key) { + if (player.ptr() != MWBase::Environment::get().getWorld()->getPlayerPtr()) + throw std::runtime_error("The argument must be a player."); + return input->getControlSwitch(key); + }; + player["setControlSwitch"] = [input](const Object& player, std::string_view key, bool v) { + if (player.ptr() != MWBase::Environment::get().getWorld()->getPlayerPtr()) + throw std::runtime_error("The argument must be a player."); + if (dynamic_cast(&player) && !dynamic_cast(&player)) + throw std::runtime_error("Only player and global scripts can toggle control switches."); + input->toggleControlSwitch(key, v); + }; } void addPlayerBindings(sol::table player, const Context& context) diff --git a/files/data/scripts/omw/camera/camera.lua b/files/data/scripts/omw/camera/camera.lua index 18fd37d730..38441f9e59 100644 --- a/files/data/scripts/omw/camera/camera.lua +++ b/files/data/scripts/omw/camera/camera.lua @@ -8,6 +8,7 @@ local async = require('openmw.async') local I = require('openmw.interfaces') local Actor = require('openmw.types').Actor +local Player = require('openmw.types').Player local settings = require('scripts.omw.camera.settings').thirdPerson local head_bobbing = require('scripts.omw.camera.head_bobbing') @@ -62,7 +63,7 @@ local previewTimer = 0 local function updatePOV(dt) local switchLimit = 0.25 - if input.isActionPressed(input.ACTION.TogglePOV) and input.getControlSwitch(input.CONTROL_SWITCH.ViewMode) then + if input.isActionPressed(input.ACTION.TogglePOV) and Player.getControlSwitch(self, Player.CONTROL_SWITCH.ViewMode) then previewTimer = previewTimer + dt if primaryMode == MODE.ThirdPerson or previewTimer >= switchLimit then third_person.standingPreview = false @@ -91,7 +92,7 @@ local idleTimer = 0 local vanityDelay = core.getGMST('fVanityDelay') local function updateVanity(dt) - local vanityAllowed = input.getControlSwitch(input.CONTROL_SWITCH.VanityMode) + local vanityAllowed = Player.getControlSwitch(self, Player.CONTROL_SWITCH.VanityMode) if vanityAllowed and idleTimer > vanityDelay and camera.getMode() ~= MODE.Vanity then camera.setMode(MODE.Vanity) end @@ -115,8 +116,8 @@ local minDistance = 30 local maxDistance = 800 local function zoom(delta) - if not input.getControlSwitch(input.CONTROL_SWITCH.ViewMode) or - not input.getControlSwitch(input.CONTROL_SWITCH.Controls) or + if not Player.getControlSwitch(self, Player.CONTROL_SWITCH.ViewMode) or + not Player.getControlSwitch(self, Player.CONTROL_SWITCH.Controls) or camera.getMode() == MODE.Static or next(noZoom) then return end diff --git a/files/data/scripts/omw/camera/move360.lua b/files/data/scripts/omw/camera/move360.lua index 76ee3be9d6..18c30ae77b 100644 --- a/files/data/scripts/omw/camera/move360.lua +++ b/files/data/scripts/omw/camera/move360.lua @@ -6,6 +6,7 @@ local util = require('openmw.util') local I = require('openmw.interfaces') local Actor = require('openmw.types').Actor +local Player = require('openmw.types').Player local MODE = camera.MODE @@ -60,8 +61,8 @@ end function M.onInputAction(action) if not active or core.isWorldPaused() or - not input.getControlSwitch(input.CONTROL_SWITCH.ViewMode) or - not input.getControlSwitch(input.CONTROL_SWITCH.Controls) or + not Player.getControlSwitch(self, Player.CONTROL_SWITCH.ViewMode) or + not Player.getControlSwitch(self, Player.CONTROL_SWITCH.Controls) or input.isActionPressed(input.ACTION.TogglePOV) or not I.Camera.isModeControlEnabled() then return diff --git a/files/data/scripts/omw/playercontrols.lua b/files/data/scripts/omw/playercontrols.lua index bea7e5392f..0bd7cf6bea 100644 --- a/files/data/scripts/omw/playercontrols.lua +++ b/files/data/scripts/omw/playercontrols.lua @@ -87,7 +87,7 @@ local function processMovement() elseif autoMove then self.controls.movement = 1 end - self.controls.jump = attemptJump and input.getControlSwitch(input.CONTROL_SWITCH.Jumping) + self.controls.jump = attemptJump and Player.getControlSwitch(self, Player.CONTROL_SWITCH.Jumping) if not settings:get('toggleSneak') then self.controls.sneak = input.isActionPressed(input.ACTION.Sneak) end @@ -107,7 +107,7 @@ local function processAttacking() end local function onFrame(dt) - local controlsAllowed = input.getControlSwitch(input.CONTROL_SWITCH.Controls) + local controlsAllowed = Player.getControlSwitch(self, Player.CONTROL_SWITCH.Controls) and not core.isWorldPaused() and not I.UI.getMode() if not movementControlsOverridden then if controlsAllowed then @@ -140,7 +140,7 @@ local function isJournalAllowed() end local function onInputAction(action) - if not input.getControlSwitch(input.CONTROL_SWITCH.Controls) then + if not Player.getControlSwitch(self, Player.CONTROL_SWITCH.Controls) then return end @@ -185,7 +185,7 @@ local function onInputAction(action) elseif action == input.ACTION.ToggleSpell and not combatControlsOverridden then if Actor.stance(self) == Actor.STANCE.Spell then Actor.setStance(self, Actor.STANCE.Nothing) - elseif input.getControlSwitch(input.CONTROL_SWITCH.Magic) then + elseif Player.getControlSwitch(self, Player.CONTROL_SWITCH.Magic) then if checkNotWerewolf() then Actor.setStance(self, Actor.STANCE.Spell) end @@ -193,7 +193,7 @@ local function onInputAction(action) elseif action == input.ACTION.ToggleWeapon and not combatControlsOverridden then if Actor.stance(self) == Actor.STANCE.Weapon then Actor.setStance(self, Actor.STANCE.Nothing) - elseif input.getControlSwitch(input.CONTROL_SWITCH.Fighting) then + elseif Player.getControlSwitch(self, Player.CONTROL_SWITCH.Fighting) then Actor.setStance(self, Actor.STANCE.Weapon) end end @@ -214,13 +214,13 @@ return { 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 `input.setControlSwitch` instead. + -- 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 `input.setControlSwitch` instead. + -- 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, diff --git a/files/lua_api/openmw/input.lua b/files/lua_api/openmw/input.lua index 3012c24e76..4ca4e5af4e 100644 --- a/files/lua_api/openmw/input.lua +++ b/files/lua_api/openmw/input.lua @@ -72,23 +72,23 @@ -- @return #number Value in range [-1, 1]. --- --- Get state of a control switch. I.e. is player able to move/fight/jump/etc. +-- Returns a human readable name for the given key code +-- @function [parent=#input] getKeyName +-- @param #KeyCode code A key code (see @{openmw.input#KEY}) +-- @return #string + +--- +-- [Deprecated, moved to types.Player] Get state of a control switch. I.e. is player able to move/fight/jump/etc. -- @function [parent=#input] getControlSwitch -- @param #ControlSwitch key Control type (see @{openmw.input#CONTROL_SWITCH}) -- @return #boolean --- --- Set state of a control switch. I.e. forbid or allow player to move/fight/jump/etc. +-- [Deprecated, moved to types.Player] Set state of a control switch. I.e. forbid or allow player to move/fight/jump/etc. -- @function [parent=#input] setControlSwitch -- @param #ControlSwitch key Control type (see @{openmw.input#CONTROL_SWITCH}) -- @param #boolean value ---- --- Returns a human readable name for the given key code --- @function [parent=#input] getKeyName --- @param #KeyCode code A key code (see @{openmw.input#KEY}) --- @return #string - --- -- String id of a @{#CONTROL_SWITCH} -- @type ControlSwitch @@ -104,7 +104,7 @@ -- @field [parent=#CONTROL_SWITCH] #ControlSwitch VanityMode Vanity view if player doesn't touch controls for a long time --- --- Values that can be used with getControlSwitch/setControlSwitch. +-- [Deprecated, moved to types.Player] Values that can be used with getControlSwitch/setControlSwitch. -- @field [parent=#input] #CONTROL_SWITCH CONTROL_SWITCH --- diff --git a/files/lua_api/openmw/types.lua b/files/lua_api/openmw/types.lua index 87cd462b6f..a5b606ea1d 100644 --- a/files/lua_api/openmw/types.lua +++ b/files/lua_api/openmw/types.lua @@ -951,6 +951,39 @@ -- @param #number stage Quest stage -- @param openmw.core#GameObject actor (optional) The actor who is the source of the journal entry, it may be used in journal entries with variables such as `%name(The speaker's name)` or `%race(The speaker's race)`. +--- +-- Get state of a control switch. I.e. is the player able to move/fight/jump/etc. +-- @function [parent=#Player] getControlSwitch +-- @param openmw.core#GameObject player +-- @param #ControlSwitch key Control type (see @{openmw.types#CONTROL_SWITCH}) +-- @return #boolean + +--- +-- Set state of a control switch. I.e. forbid or allow the player to move/fight/jump/etc. +-- Can be used only in global or player scripts. +-- @function [parent=#Player] setControlSwitch +-- @param openmw.core#GameObject player +-- @param #ControlSwitch key Control type (see @{openmw.types#CONTROL_SWITCH}) +-- @param #boolean value + +--- +-- String id of a @{#CONTROL_SWITCH} +-- @type ControlSwitch + +--- +-- @type CONTROL_SWITCH +-- @field [parent=#CONTROL_SWITCH] #ControlSwitch Controls Ability to move +-- @field [parent=#CONTROL_SWITCH] #ControlSwitch Fighting Ability to attack +-- @field [parent=#CONTROL_SWITCH] #ControlSwitch Jumping Ability to jump +-- @field [parent=#CONTROL_SWITCH] #ControlSwitch Looking Ability to change view direction +-- @field [parent=#CONTROL_SWITCH] #ControlSwitch Magic Ability to use magic +-- @field [parent=#CONTROL_SWITCH] #ControlSwitch ViewMode Ability to toggle 1st/3rd person view +-- @field [parent=#CONTROL_SWITCH] #ControlSwitch VanityMode Vanity view if player doesn't touch controls for a long time + +--- +-- Values that can be used with getControlSwitch/setControlSwitch. +-- @field [parent=#Player] #CONTROL_SWITCH CONTROL_SWITCH + -------------------------------------------------------------------------------- -- @{#Armor} functions diff --git a/scripts/data/integration_tests/test_lua_api/player.lua b/scripts/data/integration_tests/test_lua_api/player.lua index 62344af3d2..93c16a8b88 100644 --- a/scripts/data/integration_tests/test_lua_api/player.lua +++ b/scripts/data/integration_tests/test_lua_api/player.lua @@ -6,12 +6,12 @@ local input = require('openmw.input') local types = require('openmw.types') local nearby = require('openmw.nearby') -input.setControlSwitch(input.CONTROL_SWITCH.Fighting, false) -input.setControlSwitch(input.CONTROL_SWITCH.Jumping, false) -input.setControlSwitch(input.CONTROL_SWITCH.Looking, false) -input.setControlSwitch(input.CONTROL_SWITCH.Magic, false) -input.setControlSwitch(input.CONTROL_SWITCH.VanityMode, false) -input.setControlSwitch(input.CONTROL_SWITCH.ViewMode, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Fighting, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Jumping, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Looking, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Magic, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.VanityMode, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.ViewMode, false) testing.registerLocalTest('playerRotation', function() diff --git a/scripts/data/morrowind_tests/player.lua b/scripts/data/morrowind_tests/player.lua index b9e791829d..c366d91ebd 100644 --- a/scripts/data/morrowind_tests/player.lua +++ b/scripts/data/morrowind_tests/player.lua @@ -6,12 +6,12 @@ local util = require('openmw.util') local types = require('openmw.types') local nearby = require('openmw.nearby') -input.setControlSwitch(input.CONTROL_SWITCH.Fighting, false) -input.setControlSwitch(input.CONTROL_SWITCH.Jumping, false) -input.setControlSwitch(input.CONTROL_SWITCH.Looking, false) -input.setControlSwitch(input.CONTROL_SWITCH.Magic, false) -input.setControlSwitch(input.CONTROL_SWITCH.VanityMode, false) -input.setControlSwitch(input.CONTROL_SWITCH.ViewMode, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Fighting, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Jumping, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Looking, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.Magic, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.VanityMode, false) +types.Player.setControlSwitch(self, types.Player.CONTROL_SWITCH.ViewMode, false) testing.registerLocalTest('Player should be able to walk up stairs in Ebonheart docks (#4247)', function()