diff --git a/apps/openmw/mwlua/actions.cpp b/apps/openmw/mwlua/actions.cpp index 1664501f4f..95a33fed0d 100644 --- a/apps/openmw/mwlua/actions.cpp +++ b/apps/openmw/mwlua/actions.cpp @@ -41,7 +41,6 @@ namespace MWLua { MWWorld::Ptr newObj = world->moveObject(obj, cell, mPos.x(), mPos.y(), mPos.z()); world->rotateObject(newObj, mRot.x(), mRot.y(), mRot.z()); - worldView.getObjectRegistry()->registerPtr(newObj); } } diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index 3c67be5418..e01273bb84 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -81,7 +81,7 @@ namespace MWLua throw std::logic_error("Player Refnum was changed unexpectedly"); if (!mPlayer.isInCell() || !newPlayerPtr.isInCell() || mPlayer.getCell() != newPlayerPtr.getCell()) { - mPlayer = newPlayerPtr; + mPlayer = newPlayerPtr; // player was moved to another cell, update ptr in registry objectRegistry->registerPtr(mPlayer); } } @@ -123,10 +123,11 @@ namespace MWLua } // Engine handlers in local scripts - if (mPlayerScripts) + PlayerScripts* playerScripts = dynamic_cast(mPlayer.getRefData().getLuaScripts()); + if (playerScripts) { for (const SDL_Keysym& key : mKeyPressEvents) - mPlayerScripts->keyPress(key); + playerScripts->keyPress(key); } mKeyPressEvents.clear(); @@ -186,7 +187,6 @@ namespace MWLua mActorAddedEvents.clear(); mLocalEngineEvents.clear(); mPlayerChanged = false; - mPlayerScripts = nullptr; mWorldView.clear(); if (!mPlayer.isEmpty()) { @@ -202,12 +202,10 @@ namespace MWLua throw std::logic_error("Player is initialized twice"); mWorldView.objectAddedToScene(ptr); mPlayer = ptr; - MWWorld::RefData& refData = ptr.getRefData(); - if (!refData.getLuaScripts()) - createLocalScripts(ptr); - if (!mPlayerScripts) - throw std::logic_error("mPlayerScripts not initialized"); - mActiveLocalScripts.insert(mPlayerScripts); + LocalScripts* localScripts = ptr.getRefData().getLuaScripts(); + if (!localScripts) + localScripts = createLocalScripts(ptr); + mActiveLocalScripts.insert(localScripts); mLocalEngineEvents.push_back({getId(ptr), LocalScripts::OnActive{}}); mPlayerChanged = true; } @@ -269,10 +267,14 @@ namespace MWLua void LuaManager::addLocalScript(const MWWorld::Ptr& ptr, const std::string& scriptPath) { - MWWorld::RefData& refData = ptr.getRefData(); - if (!refData.getLuaScripts()) - mActiveLocalScripts.insert(createLocalScripts(ptr)); - refData.getLuaScripts()->addNewScript(scriptPath); + LocalScripts* localScripts = ptr.getRefData().getLuaScripts(); + if (!localScripts) + { + localScripts = createLocalScripts(ptr); + if (ptr.isInCell() && MWBase::Environment::get().getWorld()->isCellActive(ptr.getCell())) + mActiveLocalScripts.insert(localScripts); + } + localScripts->addNewScript(scriptPath); } LocalScripts* LuaManager::createLocalScripts(const MWWorld::Ptr& ptr) @@ -282,8 +284,7 @@ namespace MWLua // so we can't just check ptr == mPlayer here. if (*ptr.getCellRef().getRefIdPtr() == "player") { - mPlayerScripts = new PlayerScripts(&mLua, LObject(getId(ptr), mWorldView.getObjectRegistry())); - scripts = std::shared_ptr(mPlayerScripts); + scripts = std::make_shared(&mLua, LObject(getId(ptr), mWorldView.getObjectRegistry())); scripts->addPackage("openmw.ui", mUserInterfacePackage); scripts->addPackage("openmw.camera", mCameraPackage); } diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index be7174a35a..df87457b23 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -82,7 +82,6 @@ namespace MWLua bool mPlayerChanged = false; MWWorld::Ptr mPlayer; - PlayerScripts* mPlayerScripts = nullptr; GlobalEventQueue mGlobalEvents; LocalEventQueue mLocalEvents; diff --git a/apps/openmw/mwlua/object.cpp b/apps/openmw/mwlua/object.cpp index e3f5323736..696179d003 100644 --- a/apps/openmw/mwlua/object.cpp +++ b/apps/openmw/mwlua/object.cpp @@ -118,16 +118,16 @@ namespace MWLua mLastAssignedId.unset(); } - MWWorld::Ptr ObjectRegistry::getPtr(ObjectId id, bool onlyActive) + MWWorld::Ptr ObjectRegistry::getPtr(ObjectId id, bool local) { MWWorld::Ptr ptr; auto it = mObjectMapping.find(id); if (it != mObjectMapping.end()) ptr = it->second; - if (onlyActive) + if (local) { - // TODO: add flag `isActive` to LiveCellRefBase. Return empty Ptr if the flag is not set. - // Needed because in multiplayer mode inactive objects will not be synchronized, so will likely be out of date. + // TODO: Return ptr only if it is active or was active in the previous frame, otherwise return empty. + // Needed because in multiplayer inactive objects will not be synchronized, so an be out of date. } else { diff --git a/apps/openmw/mwlua/object.hpp b/apps/openmw/mwlua/object.hpp index b45c8e247c..c0b6bf1919 100644 --- a/apps/openmw/mwlua/object.hpp +++ b/apps/openmw/mwlua/object.hpp @@ -35,10 +35,9 @@ namespace MWLua ObjectId deregisterPtr(const MWWorld::Ptr& ptr); // Returns Ptr by id. If object is not found, returns empty Ptr. - // If onlyActive = true, returns non-empty ptr only if it is registered and is in an active cell. - // If onlyActive = false, tries to load and register the object if it is not loaded yet. - // NOTE: `onlyActive` logic is not yet implemented. - MWWorld::Ptr getPtr(ObjectId id, bool onlyActive); + // If local = true, returns non-empty ptr only if it can be used in local scripts + // (i.e. is active or was active in the previous frame). + MWWorld::Ptr getPtr(ObjectId id, bool local); // Needed only for saving/loading. const ObjectId& getLastAssignedId() const { return mLastAssignedId; } @@ -46,8 +45,6 @@ namespace MWLua private: friend class Object; - friend class GObject; - friend class LObject; friend class LuaManager; bool mChanged = false; diff --git a/docs/source/reference/lua-scripting/overview.rst b/docs/source/reference/lua-scripting/overview.rst index 635aeef462..d3ce319d01 100644 --- a/docs/source/reference/lua-scripting/overview.rst +++ b/docs/source/reference/lua-scripting/overview.rst @@ -52,6 +52,9 @@ Global scripts Local scripts Lua scripts that are attached to some game object. A local script is active only if the object it is attached to is in an active cell. There are no limitations to the number of local scripts on one object. Local scripts can be attached to (or detached from) any object at any moment by a global script. In some cases inactive local scripts still can run code (for example during saving and loading), but while inactive they can not see nearby objects. +.. note:: + Currently scripts on objects in a container or an inventory are considered inactive. Probably later this behaviour will be changed. + Player scripts A specific kind of local scripts; *player script* is a local script that is attached to a player. It can do everything that a normal local script can do, plus some player-specific functionality (e.g. control UI and camera).