mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-29 13:20:35 +00:00
Additional Lua bindings for cells
This commit is contained in:
parent
2725a9d7f4
commit
ce7f6f31c9
@ -33,7 +33,8 @@ namespace MWLua
|
||||
auto cell = c.mStore->getCell();
|
||||
std::stringstream res;
|
||||
if (cell->isExterior())
|
||||
res << "exterior(" << cell->getGridX() << ", " << cell->getGridY() << ")";
|
||||
res << "exterior(" << cell->getGridX() << ", " << cell->getGridY() << ", "
|
||||
<< cell->getWorldSpace().toDebugString() << ")";
|
||||
else
|
||||
res << "interior(" << cell->getNameId() << ")";
|
||||
return res.str();
|
||||
@ -42,6 +43,8 @@ namespace MWLua
|
||||
cellT["name"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->getNameId(); });
|
||||
cellT["region"] = sol::readonly_property(
|
||||
[](const CellT& c) -> std::string { return c.mStore->getCell()->getRegion().serializeText(); });
|
||||
cellT["worldSpaceId"] = sol::readonly_property(
|
||||
[](const CellT& c) -> std::string { return c.mStore->getCell()->getWorldSpace().serializeText(); });
|
||||
cellT["gridX"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->getGridX(); });
|
||||
cellT["gridY"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->getGridY(); });
|
||||
cellT["hasWater"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->hasWater(); });
|
||||
@ -67,13 +70,15 @@ namespace MWLua
|
||||
if (!ptr.isInCell())
|
||||
return false;
|
||||
MWWorld::CellStore* cell = ptr.getCell();
|
||||
return cell == c.mStore || (cell->isExterior() && c.mStore->isExterior());
|
||||
return cell == c.mStore || (cell->getCell()->getWorldSpace() == c.mStore->getCell()->getWorldSpace());
|
||||
};
|
||||
|
||||
if constexpr (std::is_same_v<CellT, GCell>)
|
||||
{ // only for global scripts
|
||||
cellT["getAll"] = [ids = getPackageToTypeTable(context.mLua->sol())](
|
||||
const CellT& cell, sol::optional<sol::table> type) {
|
||||
if (cell.mStore->getState() != MWWorld::CellStore::State_Loaded)
|
||||
cell.mStore->load();
|
||||
ObjectIdList res = std::make_shared<std::vector<ObjectId>>();
|
||||
auto visitor = [&](const MWWorld::Ptr& ptr) {
|
||||
if (ptr.getRefData().isDeleted())
|
||||
|
@ -34,6 +34,21 @@
|
||||
#include "types/types.hpp"
|
||||
#include "uibindings.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct CellsStore
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
namespace sol
|
||||
{
|
||||
template <>
|
||||
struct is_automagical<MWLua::CellsStore> : std::false_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
||||
@ -68,7 +83,7 @@ namespace MWLua
|
||||
{
|
||||
auto* lua = context.mLua;
|
||||
sol::table api(lua->sol(), sol::create);
|
||||
api["API_REVISION"] = 37;
|
||||
api["API_REVISION"] = 38;
|
||||
api["quit"] = [lua]() {
|
||||
Log(Debug::Warning) << "Quit requested by a Lua script.\n" << lua->debugTraceback();
|
||||
MWBase::Environment::get().getStateManager()->requestQuit();
|
||||
@ -106,17 +121,58 @@ namespace MWLua
|
||||
return LuaUtil::makeReadOnly(api);
|
||||
}
|
||||
|
||||
static void addCellGetters(sol::table& api, const Context& context)
|
||||
{
|
||||
api["getCellByName"] = [](std::string_view name) {
|
||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(name, /*forceLoad=*/false) };
|
||||
};
|
||||
api["getExteriorCell"] = [](int x, int y, sol::object cellOrName) {
|
||||
ESM::RefId worldspace;
|
||||
if (cellOrName.is<GCell>())
|
||||
worldspace = cellOrName.as<GCell>().mStore->getCell()->getWorldSpace();
|
||||
else if (cellOrName.is<std::string_view>() && !cellOrName.as<std::string_view>().empty())
|
||||
worldspace = MWBase::Environment::get()
|
||||
.getWorldModel()
|
||||
->getCell(cellOrName.as<std::string_view>())
|
||||
.getCell()
|
||||
->getWorldSpace();
|
||||
else
|
||||
worldspace = ESM::Cell::sDefaultWorldspaceId;
|
||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getExterior(
|
||||
ESM::ExteriorCellLocation(x, y, worldspace), /*forceLoad=*/false) };
|
||||
};
|
||||
|
||||
const MWWorld::Store<ESM::Cell>* cells3Store = &MWBase::Environment::get().getESMStore()->get<ESM::Cell>();
|
||||
const MWWorld::Store<ESM4::Cell>* cells4Store = &MWBase::Environment::get().getESMStore()->get<ESM4::Cell>();
|
||||
sol::usertype<CellsStore> cells = context.mLua->sol().new_usertype<CellsStore>("Cells");
|
||||
cells[sol::meta_function::length]
|
||||
= [cells3Store, cells4Store](const CellsStore&) { return cells3Store->getSize() + cells4Store->getSize(); };
|
||||
cells[sol::meta_function::index] = [cells3Store, cells4Store](const CellsStore&, size_t index) -> GCell {
|
||||
index--; // Translate from Lua's 1-based indexing.
|
||||
if (index < cells3Store->getSize())
|
||||
{
|
||||
const ESM::Cell* cellRecord = cells3Store->at(index);
|
||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(
|
||||
cellRecord->mId, /*forceLoad=*/false) };
|
||||
}
|
||||
else
|
||||
{
|
||||
const ESM4::Cell* cellRecord = cells4Store->at(index - cells3Store->getSize());
|
||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(
|
||||
cellRecord->mId, /*forceLoad=*/false) };
|
||||
}
|
||||
};
|
||||
cells[sol::meta_function::pairs] = context.mLua->sol()["ipairsForArray"].template get<sol::function>();
|
||||
cells[sol::meta_function::ipairs] = context.mLua->sol()["ipairsForArray"].template get<sol::function>();
|
||||
api["cells"] = CellsStore{};
|
||||
}
|
||||
|
||||
static sol::table initWorldPackage(const Context& context)
|
||||
{
|
||||
sol::table api(context.mLua->sol(), sol::create);
|
||||
WorldView* worldView = context.mWorldView;
|
||||
addTimeBindings(api, context, true);
|
||||
api["getCellByName"]
|
||||
= [](std::string_view name) { return GCell{ &MWBase::Environment::get().getWorldModel()->getCell(name) }; };
|
||||
api["getExteriorCell"] = [](int x, int y) {
|
||||
return GCell{ &MWBase::Environment::get().getWorldModel()->getExterior(
|
||||
ESM::ExteriorCellLocation(x, y, ESM::Cell::sDefaultWorldspaceId)) };
|
||||
};
|
||||
addCellGetters(api, context);
|
||||
api["activeActors"] = GObjectList{ worldView->getActorsInScene() };
|
||||
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.
|
||||
|
@ -413,6 +413,14 @@ namespace MWWorld
|
||||
size_t getExtSize() const;
|
||||
size_t getIntSize() const;
|
||||
|
||||
const ESM::Cell* at(size_t index) const
|
||||
{
|
||||
if (index < mSharedInt.size())
|
||||
return mSharedInt.at(index);
|
||||
else
|
||||
return mSharedExt.at(index - mSharedInt.size());
|
||||
}
|
||||
|
||||
void listIdentifier(std::vector<ESM::RefId>& list) const override;
|
||||
|
||||
ESM::Cell* insert(const ESM::Cell& cell);
|
||||
|
@ -160,7 +160,7 @@ MWWorld::WorldModel::WorldModel(const MWWorld::ESMStore& store, ESM::ReadersCach
|
||||
{
|
||||
}
|
||||
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getExterior(ESM::ExteriorCellLocation cellIndex)
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getExterior(ESM::ExteriorCellLocation cellIndex, bool forceLoad)
|
||||
{
|
||||
std::map<ESM::ExteriorCellLocation, CellStore*>::iterator result;
|
||||
|
||||
@ -211,7 +211,7 @@ MWWorld::CellStore& MWWorld::WorldModel::getExterior(ESM::ExteriorCellLocation c
|
||||
result = mExteriors.emplace(cellIndex, cellStore).first;
|
||||
}
|
||||
}
|
||||
if (result->second->getState() != CellStore::State_Loaded)
|
||||
if (forceLoad && result->second->getState() != CellStore::State_Loaded)
|
||||
{
|
||||
result->second->load();
|
||||
}
|
||||
@ -234,22 +234,20 @@ MWWorld::CellStore* MWWorld::WorldModel::getInteriorOrNull(std::string_view name
|
||||
return nullptr; // Cell not found
|
||||
result = mInteriors.emplace(name, newCellStore).first;
|
||||
}
|
||||
|
||||
if (result->second->getState() != CellStore::State_Loaded)
|
||||
result->second->load();
|
||||
|
||||
return result->second;
|
||||
}
|
||||
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getInterior(std::string_view name)
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getInterior(std::string_view name, bool forceLoad)
|
||||
{
|
||||
CellStore* res = getInteriorOrNull(name);
|
||||
if (res == nullptr)
|
||||
throw std::runtime_error("Interior not found: '" + std::string(name) + "'");
|
||||
if (forceLoad && res->getState() != CellStore::State_Loaded)
|
||||
res->load();
|
||||
return *res;
|
||||
}
|
||||
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getCell(const ESM::RefId& id)
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getCell(const ESM::RefId& id, bool forceLoad)
|
||||
{
|
||||
auto result = mCells.find(id);
|
||||
if (result != mCells.end())
|
||||
@ -257,7 +255,8 @@ MWWorld::CellStore& MWWorld::WorldModel::getCell(const ESM::RefId& id)
|
||||
|
||||
if (const auto* exteriorId = id.getIf<ESM::ESM3ExteriorCellRefId>())
|
||||
return getExterior(
|
||||
ESM::ExteriorCellLocation(exteriorId->getX(), exteriorId->getY(), ESM::Cell::sDefaultWorldspaceId));
|
||||
ESM::ExteriorCellLocation(exteriorId->getX(), exteriorId->getY(), ESM::Cell::sDefaultWorldspaceId),
|
||||
forceLoad);
|
||||
|
||||
const ESM4::Cell* cell4 = mStore.get<ESM4::Cell>().search(id);
|
||||
CellStore* newCellStore = nullptr;
|
||||
@ -281,17 +280,21 @@ MWWorld::CellStore& MWWorld::WorldModel::getCell(const ESM::RefId& id)
|
||||
{
|
||||
mInteriors.emplace(newCellStore->getCell()->getNameId(), newCellStore);
|
||||
}
|
||||
if (newCellStore->getState() != CellStore::State_Loaded)
|
||||
if (forceLoad && newCellStore->getState() != CellStore::State_Loaded)
|
||||
{
|
||||
newCellStore->load();
|
||||
}
|
||||
return *newCellStore;
|
||||
}
|
||||
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getCell(std::string_view name)
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getCell(std::string_view name, bool forceLoad)
|
||||
{
|
||||
if (CellStore* res = getInteriorOrNull(name)) // first try interiors
|
||||
{
|
||||
if (forceLoad && res->getState() != CellStore::State_Loaded)
|
||||
res->load();
|
||||
return *res;
|
||||
}
|
||||
|
||||
// try named exteriors
|
||||
const ESM::Cell* cell = mStore.get<ESM::Cell>().searchExtByName(name);
|
||||
@ -319,7 +322,8 @@ MWWorld::CellStore& MWWorld::WorldModel::getCell(std::string_view name)
|
||||
if (!cell)
|
||||
throw std::runtime_error(std::string("Can't find cell with name ") + std::string(name));
|
||||
|
||||
return getExterior(ESM::ExteriorCellLocation(cell->getGridX(), cell->getGridY(), ESM::Cell::sDefaultWorldspaceId));
|
||||
return getExterior(
|
||||
ESM::ExteriorCellLocation(cell->getGridX(), cell->getGridY(), ESM::Cell::sDefaultWorldspaceId), forceLoad);
|
||||
}
|
||||
|
||||
MWWorld::CellStore& MWWorld::WorldModel::getCellByPosition(
|
||||
|
@ -65,10 +65,10 @@ namespace MWWorld
|
||||
|
||||
void clear();
|
||||
|
||||
CellStore& getExterior(ESM::ExteriorCellLocation cellIndex);
|
||||
CellStore& getInterior(std::string_view name);
|
||||
CellStore& getCell(std::string_view name); // interior or named exterior
|
||||
CellStore& getCell(const ESM::RefId& Id);
|
||||
CellStore& getExterior(ESM::ExteriorCellLocation cellIndex, bool forceLoad = true);
|
||||
CellStore& getInterior(std::string_view name, bool forceLoad = true);
|
||||
CellStore& getCell(std::string_view name, bool forceLoad = true); // interior or named exterior
|
||||
CellStore& getCell(const ESM::RefId& Id, bool forceLoad = true);
|
||||
|
||||
// Returns the cell that is in the same worldspace as `cellInSameWorldSpace`
|
||||
// (in case of nullptr - default exterior worldspace) and contains given position.
|
||||
|
@ -225,6 +225,7 @@
|
||||
-- @field #boolean isQuasiExterior (DEPRECATED, use `hasTag("QuasiExterior")`) Whether the cell is a quasi exterior (like interior but with the sky and the wheather).
|
||||
-- @field #number gridX Index of the cell by X (only for exteriors).
|
||||
-- @field #number gridY Index of the cell by Y (only for exteriors).
|
||||
-- @field #string worldSpaceId Id of the world space.
|
||||
-- @field #boolean hasWater True if the cell contains water.
|
||||
-- @field #boolean hasSky True if in this cell sky should be rendered.
|
||||
|
||||
|
@ -21,8 +21,14 @@
|
||||
-- @function [parent=#world] getExteriorCell
|
||||
-- @param #number gridX
|
||||
-- @param #number gridY
|
||||
-- @param #any cellOrName (optional) other cell or cell name in the same exterior world space
|
||||
-- @return openmw.core#Cell
|
||||
|
||||
---
|
||||
-- List of all cells
|
||||
-- @field [parent=#world] #list<openmw.core#Cell> cells
|
||||
-- @usage for i, cell in ipairs(world.cells) do print(cell) end
|
||||
|
||||
---
|
||||
-- Simulation time in seconds.
|
||||
-- The number of simulation seconds passed in the game world since starting a new game.
|
||||
|
Loading…
x
Reference in New Issue
Block a user