Make loaded but inactive objects available in Lua scripts.

dont-compose-content
Petr Mikheev 4 years ago
parent 403d31313c
commit 1268597676

@ -31,6 +31,8 @@ namespace MWBase
virtual void newGameStarted() = 0;
virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0;
virtual void objectRemovedFromScene(const MWWorld::Ptr& ptr) = 0;
virtual void registerObject(const MWWorld::Ptr& ptr) = 0;
virtual void deregisterObject(const MWWorld::Ptr& ptr) = 0;
virtual void keyPressed(const SDL_KeyboardEvent &arg) = 0;
struct ActorControls {

@ -134,6 +134,7 @@ namespace MWLua
scripts->processTimers(seconds, hours);
}
// Receive events
for (GlobalEvent& e : globalEvents)
mGlobalScripts.receiveEvent(e.eventName, e.eventData);
for (LocalEvent& e : localEvents)
@ -147,12 +148,7 @@ namespace MWLua
<< ". Object not found or has no attached scripts";
}
if (mPlayerChanged)
{
mPlayerChanged = false;
mGlobalScripts.playerAdded(GObject(getId(mPlayer), mWorldView.getObjectRegistry()));
}
// Engine handlers in local scripts
if (mPlayerScripts)
{
for (const SDL_Keysym key : mKeyPressEvents)
@ -167,13 +163,21 @@ namespace MWLua
mObjectActiveEvents.clear();
mObjectInactiveEvents.clear();
for (LocalScripts* scripts : mActiveLocalScripts)
scripts->update(dt);
// Engine handlers in global scripts
if (mPlayerChanged)
{
mPlayerChanged = false;
mGlobalScripts.playerAdded(GObject(getId(mPlayer), mWorldView.getObjectRegistry()));
}
for (ObjectId id : mActorAddedEvents)
mGlobalScripts.actorActive(GObject(id, mWorldView.getObjectRegistry()));
mActorAddedEvents.clear();
mGlobalScripts.update(dt);
for (LocalScripts* scripts : mActiveLocalScripts)
scripts->update(dt);
}
void LuaManager::applyQueuedChanges()
@ -212,21 +216,6 @@ namespace MWLua
}
}
void LuaManager::objectAddedToScene(const MWWorld::Ptr& ptr)
{
mWorldView.objectAddedToScene(ptr); // assigns generated RefNum if it is not set yet.
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
if (localScripts)
{
mActiveLocalScripts.insert(localScripts);
mObjectActiveEvents.push_back(localScripts);
}
if (ptr.getClass().isActor() && ptr != mPlayer)
mActorAddedEvents.push_back(getId(ptr));
}
void LuaManager::setupPlayer(const MWWorld::Ptr& ptr)
{
if (!mPlayer.isEmpty())
@ -239,9 +228,25 @@ namespace MWLua
if (!mPlayerScripts)
throw std::logic_error("mPlayerScripts not initialized");
mActiveLocalScripts.insert(mPlayerScripts);
mObjectActiveEvents.push_back(mPlayerScripts);
mPlayerChanged = true;
}
void LuaManager::objectAddedToScene(const MWWorld::Ptr& ptr)
{
mWorldView.objectAddedToScene(ptr); // assigns generated RefNum if it is not set yet.
LocalScripts* localScripts = ptr.getRefData().getLuaScripts();
if (localScripts)
{
mActiveLocalScripts.insert(localScripts);
mObjectActiveEvents.push_back(localScripts);
}
if (ptr.getClass().isActor() && ptr != mPlayer)
mActorAddedEvents.push_back(getId(ptr));
}
void LuaManager::objectRemovedFromScene(const MWWorld::Ptr& ptr)
{
mWorldView.objectRemovedFromScene(ptr);
@ -249,10 +254,19 @@ namespace MWLua
if (localScripts)
{
mActiveLocalScripts.erase(localScripts);
mObjectInactiveEvents.push_back(localScripts);
if (!mWorldView.getObjectRegistry()->getPtr(getId(ptr), true).isEmpty())
mObjectInactiveEvents.push_back(localScripts);
}
}
// TODO: call mWorldView.objectUnloaded if object is unloaded from memory (does it ever happen?) and ptr becomes invalid.
void LuaManager::registerObject(const MWWorld::Ptr& ptr)
{
mWorldView.getObjectRegistry()->registerPtr(ptr);
}
void LuaManager::deregisterObject(const MWWorld::Ptr& ptr)
{
mWorldView.getObjectRegistry()->deregisterPtr(ptr);
}
void LuaManager::keyPressed(const SDL_KeyboardEvent& arg)
@ -349,6 +363,9 @@ namespace MWLua
scripts->setSerializer(mLocalLoader.get());
scripts->load(data, true);
scripts->setSerializer(mLocalSerializer.get());
// LiveCellRef is usually copied after loading, so this Ptr will become invalid and should be deregistered.
mWorldView.getObjectRegistry()->deregisterPtr(ptr);
}
void LuaManager::reloadAllScripts()

@ -40,6 +40,8 @@ namespace MWLua
void newGameStarted() override { mGlobalScripts.newGameStarted(); }
void objectAddedToScene(const MWWorld::Ptr& ptr) override;
void objectRemovedFromScene(const MWWorld::Ptr& ptr) override;
void registerObject(const MWWorld::Ptr& ptr) override;
void deregisterObject(const MWWorld::Ptr& ptr) override;
void keyPressed(const SDL_KeyboardEvent &arg) override;
MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;

@ -18,6 +18,7 @@
#include <components/esm/doorstate.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/luamanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/world.hpp"
@ -195,6 +196,8 @@ namespace
iter->mData.enable();
MWBase::Environment::get().getWorld()->disable(MWWorld::Ptr(&*iter, cellstore));
}
else
MWBase::Environment::get().getLuaManager()->registerObject(MWWorld::Ptr(&*iter, cellstore));
return;
}
@ -206,6 +209,9 @@ namespace
MWWorld::LiveCellRef<T> ref (record);
ref.load (state);
collection.mList.push_back (ref);
MWWorld::LiveCellRefBase* base = &collection.mList.back();
MWBase::Environment::get().getLuaManager()->registerObject(MWWorld::Ptr(base, cellstore));
}
}
@ -286,16 +292,7 @@ namespace MWWorld
if (searchViaRefNum(object.getCellRef().getRefNum()).isEmpty())
throw std::runtime_error("moveTo: object is not in this cell");
// Objects with no refnum can't be handled correctly in the merging process that happens
// on a save/load, so do a simple copy & delete for these objects.
if (!object.getCellRef().getRefNum().hasContentFile())
{
MWWorld::Ptr copied = object.getClass().copyToCell(object, *cellToMoveTo, object.getRefData().getCount());
object.getRefData().setCount(0);
object.getRefData().setBaseNode(nullptr);
return copied;
}
MWBase::Environment::get().getLuaManager()->registerObject(MWWorld::Ptr(object.getBase(), cellToMoveTo));
MovedRefTracker::iterator found = mMovedHere.find(object.getBase());
if (found != mMovedHere.end())

@ -813,7 +813,8 @@ namespace MWWorld
void World::enable (const Ptr& reference)
{
// enable is a no-op for items in containers
MWBase::Environment::get().getLuaManager()->registerObject(reference);
if (!reference.isInCell())
return;
@ -864,6 +865,7 @@ namespace MWWorld
if (reference == getPlayerPtr())
throw std::runtime_error("can not disable player object");
MWBase::Environment::get().getLuaManager()->deregisterObject(reference);
reference.getRefData().disable();
if (reference.getCellRef().getRefNum().hasContentFile())

Loading…
Cancel
Save