Add special cell for objects created via Lua scripts and not yet added into the world

revert-6246b479
Petr Mikheev 2 years ago
parent 1d73780621
commit d830ae37b1

@ -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<int> 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 {

@ -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<Cell<ObjectT>> {
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<ObjectT>{ ptr.getCell() };
else
return sol::nullopt;

@ -26,6 +26,8 @@ namespace MWWorld
{
namespace
{
const ESM::RefId draftCellId = ESM::RefId::index(ESM::REC_CSTA, 0);
template <class T>
CellStore& emplaceCellStore(ESM::RefId id, const T& cell, ESMStore& store, ESM::ReadersCache& readers,
std::unordered_map<ESM::RefId, CellStore>& 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<ESM::ESM3ExteriorCellRefId>())
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))

@ -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<ESM::RefId, CellStore> mCells;
mutable std::map<std::string, CellStore*, Misc::StringUtils::CiComp> mInteriors;
mutable std::map<ESM::ExteriorCellLocation, CellStore*> mExteriors;
ESM::Cell mDraftCell;
std::vector<std::pair<ESM::RefId, CellStore*>> mIdCache;
std::size_t mIdCacheIndex = 0;
PtrRegistry mPtrRegistry;

Loading…
Cancel
Save