diff --git a/apps/openmw/mwbase/luamanager.hpp b/apps/openmw/mwbase/luamanager.hpp index e120b1403e8..06a68efe4a3 100644 --- a/apps/openmw/mwbase/luamanager.hpp +++ b/apps/openmw/mwbase/luamanager.hpp @@ -51,7 +51,7 @@ namespace MWBase virtual void objectTeleported(const MWWorld::Ptr& ptr) = 0; virtual void itemConsumed(const MWWorld::Ptr& consumable, const MWWorld::Ptr& actor) = 0; virtual void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0; - virtual void useItem(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0; + virtual void useItem(const MWWorld::Ptr& object, const MWWorld::Ptr& actor, bool force) = 0; virtual void exteriorCreated(MWWorld::CellStore& cell) = 0; virtual void questUpdated(const ESM::RefId& questId, int stage) = 0; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index decbede8569..610e34e3cd3 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -601,7 +601,7 @@ namespace MWGui } } else - MWBase::Environment::get().getLuaManager()->useItem(ptr, MWMechanics::getPlayer()); + MWBase::Environment::get().getLuaManager()->useItem(ptr, MWMechanics::getPlayer(), false); // If item is ingredient or potion don't stop drag and drop to simplify action of taking more than one 1 // item diff --git a/apps/openmw/mwlua/engineevents.cpp b/apps/openmw/mwlua/engineevents.cpp index ac1ac687ed9..c838ccfcba6 100644 --- a/apps/openmw/mwlua/engineevents.cpp +++ b/apps/openmw/mwlua/engineevents.cpp @@ -71,7 +71,7 @@ namespace MWLua MWWorld::Ptr actor = getPtr(event.mActor); if (actor.isEmpty() || obj.isEmpty()) return; - mGlobalScripts.onUseItem(GObject(obj), GObject(actor)); + mGlobalScripts.onUseItem(GObject(obj), GObject(actor), event.mForce); } void operator()(const OnConsume& event) const diff --git a/apps/openmw/mwlua/engineevents.hpp b/apps/openmw/mwlua/engineevents.hpp index 3cbc3666239..7c706edcd0f 100644 --- a/apps/openmw/mwlua/engineevents.hpp +++ b/apps/openmw/mwlua/engineevents.hpp @@ -40,6 +40,7 @@ namespace MWLua { ESM::RefNum mActor; ESM::RefNum mObject; + bool mForce; }; struct OnConsume { diff --git a/apps/openmw/mwlua/globalscripts.hpp b/apps/openmw/mwlua/globalscripts.hpp index 314a4118e6e..afaadb9d0a0 100644 --- a/apps/openmw/mwlua/globalscripts.hpp +++ b/apps/openmw/mwlua/globalscripts.hpp @@ -40,7 +40,10 @@ namespace MWLua { callEngineHandlers(mOnActivateHandlers, obj, actor); } - void onUseItem(const GObject& obj, const GObject& actor) { callEngineHandlers(mOnUseItemHandlers, obj, actor); } + void onUseItem(const GObject& obj, const GObject& actor, bool force) + { + callEngineHandlers(mOnUseItemHandlers, obj, actor, force); + } void onNewExterior(const GCell& cell) { callEngineHandlers(mOnNewExteriorHandlers, cell); } private: diff --git a/apps/openmw/mwlua/luabindings.cpp b/apps/openmw/mwlua/luabindings.cpp index ef13adb9366..8b62c5480de 100644 --- a/apps/openmw/mwlua/luabindings.cpp +++ b/apps/openmw/mwlua/luabindings.cpp @@ -330,16 +330,16 @@ namespace MWLua }, "_runStandardActivationAction"); }; - api["_runStandardUseAction"] = [context](const GObject& object, const GObject& actor) { + api["_runStandardUseAction"] = [context](const GObject& object, const GObject& actor, bool force) { context.mLuaManager->addAction( - [object, actor] { + [object, actor, force] { const MWWorld::Ptr& actorPtr = actor.ptr(); const MWWorld::Ptr& objectPtr = object.ptr(); if (actorPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) - MWBase::Environment::get().getWindowManager()->useItem(objectPtr, true); + MWBase::Environment::get().getWindowManager()->useItem(objectPtr, force); else { - std::unique_ptr action = objectPtr.getClass().use(objectPtr, true); + std::unique_ptr action = objectPtr.getClass().use(objectPtr, force); action->execute(actorPtr, true); } }, diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index c14c9ace5bb..3cbef6d9458 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -77,9 +77,9 @@ namespace MWLua { mEngineEvents.addToQueue(EngineEvents::OnActivate{ getId(actor), getId(object) }); } - void useItem(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) override + void useItem(const MWWorld::Ptr& object, const MWWorld::Ptr& actor, bool force) override { - mEngineEvents.addToQueue(EngineEvents::OnUseItem{ getId(actor), getId(object) }); + mEngineEvents.addToQueue(EngineEvents::OnUseItem{ getId(actor), getId(object), force }); } void exteriorCreated(MWWorld::CellStore& cell) override { diff --git a/docs/source/reference/lua-scripting/events.rst b/docs/source/reference/lua-scripting/events.rst index 3e689078d01..b0e600413a6 100644 --- a/docs/source/reference/lua-scripting/events.rst +++ b/docs/source/reference/lua-scripting/events.rst @@ -20,14 +20,14 @@ Examples: **UseItem** -Any script can send global event ``UseItem`` with arguments ``object`` and ``actor``. +Any script can send global event ``UseItem`` with arguments ``object``, ``actor``, and optional boolean ``force``. The actor will use (e.g. equip or consume) the object. The object should be in the actor's inventory. Example: .. code-block:: Lua - core.sendGlobalEvent('UseItem', {object = potion, actor = player}) + core.sendGlobalEvent('UseItem', {object = potion, actor = player, force = true}) UI events --------- diff --git a/files/data/scripts/omw/usehandlers.lua b/files/data/scripts/omw/usehandlers.lua index 7cc7e12f949..01203b225c5 100644 --- a/files/data/scripts/omw/usehandlers.lua +++ b/files/data/scripts/omw/usehandlers.lua @@ -4,11 +4,12 @@ local world = require('openmw.world') local handlersPerObject = {} local handlersPerType = {} -local function useItem(obj, actor) +local function useItem(obj, actor, force) + local options = { force = force or false } local handlers = handlersPerObject[obj.id] if handlers then for i = #handlers, 1, -1 do - if handlers[i](obj, actor) == false then + if handlers[i](obj, actor, options) == false then return -- skip other handlers end end @@ -16,12 +17,12 @@ local function useItem(obj, actor) handlers = handlersPerType[obj.type] if handlers then for i = #handlers, 1, -1 do - if handlers[i](obj, actor) == false then + if handlers[i](obj, actor, options) == false then return -- skip other handlers end end end - world._runStandardUseAction(obj, actor) + world._runStandardUseAction(obj, actor, force) end return { @@ -53,7 +54,7 @@ return { version = 0, --- Add new use action handler for a specific object. - -- If `handler(object, actor)` returns false, other handlers for + -- If `handler(object, actor, options)` returns false, other handlers for -- the same object (including type handlers) will be skipped. -- @function [parent=#ItemUsage] addHandlerForObject -- @param openmw.core#GameObject obj The object. @@ -68,7 +69,7 @@ return { end, --- Add new use action handler for a type of objects. - -- If `handler(object, actor)` returns false, other handlers for + -- If `handler(object, actor, options)` returns false, other handlers for -- the same object (including type handlers) will be skipped. -- @function [parent=#ItemUsage] addHandlerForType -- @param #any type A type from the `openmw.types` package. @@ -91,7 +92,7 @@ return { if not data.actor or not types.Actor.objectIsInstance(data.actor) then error('UseItem: invalid argument "actor"') end - useItem(data.object, data.actor) + useItem(data.object, data.actor, data.force) end } }