From 4016e8b383fdf6a6ecec29bb1990f4860f49b7db Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sun, 18 Jun 2023 21:19:34 +0200 Subject: [PATCH] Lua engine handler onTeleported --- apps/openmw/mwbase/luamanager.hpp | 1 + apps/openmw/mwlua/engineevents.cpp | 6 ++++++ apps/openmw/mwlua/engineevents.hpp | 6 +++++- apps/openmw/mwlua/localscripts.cpp | 4 ++-- apps/openmw/mwlua/localscripts.hpp | 2 ++ apps/openmw/mwlua/luamanagerimp.cpp | 14 ++++++++++++++ apps/openmw/mwlua/luamanagerimp.hpp | 1 + apps/openmw/mwlua/objectbindings.cpp | 2 ++ apps/openmw/mwscript/transformationextensions.cpp | 3 +++ apps/openmw/mwworld/actionteleport.cpp | 4 +++- .../reference/lua-scripting/engine_handlers.rst | 2 ++ 11 files changed, 41 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwbase/luamanager.hpp b/apps/openmw/mwbase/luamanager.hpp index d9ce24a119..fcbb6289f9 100644 --- a/apps/openmw/mwbase/luamanager.hpp +++ b/apps/openmw/mwbase/luamanager.hpp @@ -47,6 +47,7 @@ namespace MWBase virtual void gameLoaded() = 0; virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0; virtual void objectRemovedFromScene(const MWWorld::Ptr& ptr) = 0; + 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 exteriorCreated(MWWorld::CellStore& cell) = 0; diff --git a/apps/openmw/mwlua/engineevents.cpp b/apps/openmw/mwlua/engineevents.cpp index c7418ad356..569eb22bcf 100644 --- a/apps/openmw/mwlua/engineevents.cpp +++ b/apps/openmw/mwlua/engineevents.cpp @@ -48,6 +48,12 @@ namespace MWLua scripts->setActive(false); } + void operator()(const OnTeleported& event) const + { + if (auto* scripts = getLocalScripts(event.mObject)) + scripts->onTeleported(); + } + void operator()(const OnActivate& event) const { MWWorld::Ptr obj = getPtr(event.mObject); diff --git a/apps/openmw/mwlua/engineevents.hpp b/apps/openmw/mwlua/engineevents.hpp index b20ba2a3e8..ac854abd4a 100644 --- a/apps/openmw/mwlua/engineevents.hpp +++ b/apps/openmw/mwlua/engineevents.hpp @@ -27,6 +27,10 @@ namespace MWLua { ESM::RefNum mObject; }; + struct OnTeleported + { + ESM::RefNum mObject; + }; struct OnActivate { ESM::RefNum mActor; @@ -41,7 +45,7 @@ namespace MWLua { MWWorld::CellStore& mCell; }; - using Event = std::variant; + using Event = std::variant; void clear() { mQueue.clear(); } void addToQueue(Event e) { mQueue.push_back(std::move(e)); } diff --git a/apps/openmw/mwlua/localscripts.cpp b/apps/openmw/mwlua/localscripts.cpp index 26f6b75299..8cf383e985 100644 --- a/apps/openmw/mwlua/localscripts.cpp +++ b/apps/openmw/mwlua/localscripts.cpp @@ -169,8 +169,8 @@ namespace MWLua , mData(obj) { this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData)); - registerEngineHandlers( - { &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers }); + registerEngineHandlers({ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers, + &mOnTeleportedHandlers }); } void LocalScripts::setActive(bool active) diff --git a/apps/openmw/mwlua/localscripts.hpp b/apps/openmw/mwlua/localscripts.hpp index ea54321697..6b1555868d 100644 --- a/apps/openmw/mwlua/localscripts.hpp +++ b/apps/openmw/mwlua/localscripts.hpp @@ -70,6 +70,7 @@ namespace MWLua void setActive(bool active); void onConsume(const LObject& consumable) { callEngineHandlers(mOnConsumeHandlers, consumable); } void onActivated(const LObject& actor) { callEngineHandlers(mOnActivatedHandlers, actor); } + void onTeleported() { callEngineHandlers(mOnTeleportedHandlers); } void applyStatsCache(); @@ -81,6 +82,7 @@ namespace MWLua EngineHandlerList mOnInactiveHandlers{ "onInactive" }; EngineHandlerList mOnConsumeHandlers{ "onConsume" }; EngineHandlerList mOnActivatedHandlers{ "onActivated" }; + EngineHandlerList mOnTeleportedHandlers{ "onTeleported" }; }; } diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index b2a1e4ea2d..f7386ca61d 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -178,6 +178,20 @@ namespace MWLua } } + void LuaManager::objectTeleported(const MWWorld::Ptr& ptr) + { + if (ptr == mPlayer) + { + // For player run the onTeleported handler immediately, + // so it can adjust camera position after teleporting. + PlayerScripts* playerScripts = dynamic_cast(mPlayer.getRefData().getLuaScripts()); + if (playerScripts) + playerScripts->onTeleported(); + } + else + mEngineEvents.addToQueue(EngineEvents::OnTeleported{ getId(ptr) }); + } + void LuaManager::questUpdated(const ESM::RefId& questId, int stage) { if (mPlayer.isEmpty()) diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index 74976f1127..01315bb9df 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -75,6 +75,7 @@ namespace MWLua { mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell }); } + void objectTeleported(const MWWorld::Ptr& ptr) override; void questUpdated(const ESM::RefId& questId, int stage) override; MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override; diff --git a/apps/openmw/mwlua/objectbindings.cpp b/apps/openmw/mwlua/objectbindings.cpp index 24c43d739a..599dd8ca5d 100644 --- a/apps/openmw/mwlua/objectbindings.cpp +++ b/apps/openmw/mwlua/objectbindings.cpp @@ -95,6 +95,7 @@ namespace MWLua world->rotateObject(newPtr, rot); if (placeOnGround) world->adjustPosition(newPtr, true); + MWBase::Environment::get().getLuaManager()->objectTeleported(newPtr); } void teleportNotPlayer(const MWWorld::Ptr& ptr, MWWorld::CellStore* destCell, const osg::Vec3f& pos, @@ -119,6 +120,7 @@ namespace MWLua } if (!newPtr.getRefData().isEnabled()) world->enable(newPtr); + MWBase::Environment::get().getLuaManager()->objectTeleported(newPtr); } template diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index 5f142856bd..614fbbe26f 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -11,6 +11,7 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/luamanager.hpp" #include "../mwbase/world.hpp" #include "../mwworld/cellstore.hpp" @@ -436,6 +437,7 @@ namespace MWScript bool cellActive = MWBase::Environment::get().getWorldScene()->isCellActive(*ptr.getCell()); ptr.getClass().adjustPosition(ptr, isPlayer || !cellActive); + MWBase::Environment::get().getLuaManager()->objectTeleported(ptr); } }; @@ -492,6 +494,7 @@ namespace MWScript world->rotateObject(ptr, rot); bool cellActive = MWBase::Environment::get().getWorldScene()->isCellActive(*ptr.getCell()); ptr.getClass().adjustPosition(ptr, isPlayer || !cellActive); + MWBase::Environment::get().getLuaManager()->objectTeleported(ptr); } }; diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 2aaa16cd0b..95c136ac86 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -4,6 +4,7 @@ #include #include "../mwbase/environment.hpp" +#include "../mwbase/luamanager.hpp" #include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/world.hpp" @@ -65,7 +66,6 @@ namespace MWWorld actor.getClass().getCreatureStats(actor).getAiSequence().stopCombat(); return; } - else teleported = world->moveObject(actor, &worldModel->getCell(mCellId), mPosition.asVec3(), true, true); } @@ -75,6 +75,8 @@ namespace MWWorld .getCreatureStats(teleported) .getActiveSpells() .purgeEffect(actor, ESM::MagicEffect::WaterWalking); + + MWBase::Environment::get().getLuaManager()->objectTeleported(teleported); } void ActionTeleport::getFollowers( diff --git a/docs/source/reference/lua-scripting/engine_handlers.rst b/docs/source/reference/lua-scripting/engine_handlers.rst index 5668bf7cba..64bfe061ef 100644 --- a/docs/source/reference/lua-scripting/engine_handlers.rst +++ b/docs/source/reference/lua-scripting/engine_handlers.rst @@ -64,6 +64,8 @@ Engine handler is a function defined by a script, that can be called by the engi - | Object became inactive. Since it is inactive the handler | can not access anything nearby, but it is possible to send | an event to global scripts. + * - onTeleported() + - Object was teleported. * - onActivated(actor) - | Called on an object when an actor activates it. Note that picking | up an item is also an activation and works this way: (1) a copy of