diff --git a/apps/openmw/mwlua/luabindings.cpp b/apps/openmw/mwlua/luabindings.cpp index aa14c022e3..1804ea4004 100644 --- a/apps/openmw/mwlua/luabindings.cpp +++ b/apps/openmw/mwlua/luabindings.cpp @@ -21,8 +21,8 @@ #include "../mwworld/class.hpp" #include "../mwworld/esmstore.hpp" #include "../mwworld/manualref.hpp" -#include "../mwworld/scene.hpp" #include "../mwworld/store.hpp" +#include "../mwworld/worldmodel.hpp" #include "luaevents.hpp" #include "luamanagerimp.hpp" @@ -226,13 +226,11 @@ namespace MWLua api["activeActors"] = GObjectList{ worldView->getActorsInScene() }; api["players"] = GObjectList{ worldView->getPlayers() }; api["createObject"] = [](std::string_view recordId, sol::optional count) -> GObject { - // Doesn't matter which cell to use because the new object will be in disabled state. - MWWorld::CellStore* cell = MWBase::Environment::get().getWorldScene()->getCurrentCell(); - MWWorld::ManualRef mref(*MWBase::Environment::get().getESMStore(), ESM::RefId::deserializeText(recordId)); const MWWorld::Ptr& ptr = mref.getPtr(); ptr.getRefData().disable(); - MWWorld::Ptr newPtr = ptr.getClass().copyToCell(ptr, *cell, count.value_or(1)); + MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getDraftCell(); + MWWorld::Ptr newPtr = ptr.getClass().copyToCell(ptr, cell, count.value_or(1)); return GObject(newPtr); }; api["getObjectByFormId"] = [](std::string_view formIdStr) -> GObject { diff --git a/apps/openmw/mwlua/objectbindings.cpp b/apps/openmw/mwlua/objectbindings.cpp index 1ebc0702b1..36e692abae 100644 --- a/apps/openmw/mwlua/objectbindings.cpp +++ b/apps/openmw/mwlua/objectbindings.cpp @@ -182,7 +182,8 @@ namespace MWLua [](const ObjectT& o) -> std::string { return o.ptr().getCellRef().getRefId().serializeText(); }); objectT["cell"] = sol::readonly_property([](const ObjectT& o) -> sol::optional> { const MWWorld::Ptr& ptr = o.ptr(); - if (ptr.isInCell()) + MWWorld::WorldModel* wm = MWBase::Environment::get().getWorldModel(); + if (ptr.isInCell() && ptr.getCell() != &wm->getDraftCell()) return Cell{ ptr.getCell() }; else return sol::nullopt; diff --git a/apps/openmw/mwworld/worldmodel.cpp b/apps/openmw/mwworld/worldmodel.cpp index acf2c8bc1a..65eabadaa1 100644 --- a/apps/openmw/mwworld/worldmodel.cpp +++ b/apps/openmw/mwworld/worldmodel.cpp @@ -26,6 +26,8 @@ namespace MWWorld { namespace { + const ESM::RefId draftCellId = ESM::RefId::index(ESM::REC_CSTA, 0); + template CellStore& emplaceCellStore(ESM::RefId id, const T& cell, ESMStore& store, ESM::ReadersCache& readers, std::unordered_map& cells) @@ -159,6 +161,7 @@ MWWorld::WorldModel::WorldModel(MWWorld::ESMStore& store, ESM::ReadersCache& rea , mReaders(readers) , mIdCache(Settings::cells().mPointersCacheSize, { ESM::RefId(), nullptr }) { + mDraftCell.mId = draftCellId; } namespace MWWorld @@ -229,6 +232,13 @@ namespace MWWorld if (it != mCells.end()) return &it->second; + if (id == draftCellId) + { + CellStore& cellStore = emplaceCellStore(id, Cell(mDraftCell), mStore, mReaders, mCells); + cellStore.load(); + return &cellStore; + } + if (const auto* exteriorId = id.getIf()) return &getExterior( ESM::ExteriorCellLocation(exteriorId->getX(), exteriorId->getY(), ESM::Cell::sDefaultWorldspaceId), @@ -261,6 +271,11 @@ namespace MWWorld return *result; } + CellStore& WorldModel::getDraftCell() const + { + return getCell(draftCellId); + } + CellStore* WorldModel::findCell(std::string_view name, bool forceLoad) const { if (CellStore* const cellStore = findInterior(name, forceLoad)) diff --git a/apps/openmw/mwworld/worldmodel.hpp b/apps/openmw/mwworld/worldmodel.hpp index 41025ce820..85238dbda8 100644 --- a/apps/openmw/mwworld/worldmodel.hpp +++ b/apps/openmw/mwworld/worldmodel.hpp @@ -53,6 +53,10 @@ namespace MWWorld CellStore& getCell(ESM::RefId Id, bool forceLoad = true) const; + // Returns a special cell that is never active. Can be used for creating objects + // without adding them to the scene. + CellStore& getDraftCell() const; + CellStore* findInterior(std::string_view name, bool forceLoad = true) const; CellStore& getInterior(std::string_view name, bool forceLoad = true) const; @@ -103,6 +107,7 @@ namespace MWWorld mutable std::unordered_map mCells; mutable std::map mInteriors; mutable std::map mExteriors; + ESM::Cell mDraftCell; std::vector> mIdCache; std::size_t mIdCacheIndex = 0; PtrRegistry mPtrRegistry;