mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-10 03:39:55 +00:00
Merge branch 'teleport' into 'master'
Additional Lua bindings for cells and fixes for teleporting See merge request OpenMW/openmw!3017
This commit is contained in:
commit
5fba79ece3
@ -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.
|
||||
|
@ -66,7 +66,8 @@ namespace MWLua
|
||||
return &wm->getCellByPosition(pos, cell);
|
||||
}
|
||||
|
||||
void teleportPlayer(MWWorld::CellStore* destCell, const osg::Vec3f& pos, const osg::Vec3f& rot)
|
||||
void teleportPlayer(
|
||||
MWWorld::CellStore* destCell, const osg::Vec3f& pos, const osg::Vec3f& rot, bool placeOnGround)
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
ESM::Position esmPos;
|
||||
@ -74,20 +75,38 @@ namespace MWLua
|
||||
std::memcpy(esmPos.pos, &pos, sizeof(osg::Vec3f));
|
||||
std::memcpy(esmPos.rot, &rot, sizeof(osg::Vec3f));
|
||||
MWWorld::Ptr ptr = world->getPlayerPtr();
|
||||
ptr.getClass().getCreatureStats(ptr).land(false);
|
||||
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
stats.land(true);
|
||||
stats.setTeleported(true);
|
||||
world->getPlayer().setTeleported(true);
|
||||
world->changeToCell(destCell->getCell()->getId(), esmPos, true);
|
||||
world->changeToCell(destCell->getCell()->getId(), esmPos, false);
|
||||
MWWorld::Ptr newPtr = world->getPlayerPtr();
|
||||
world->moveObject(newPtr, pos);
|
||||
world->rotateObject(newPtr, rot);
|
||||
if (placeOnGround)
|
||||
world->adjustPosition(newPtr, true);
|
||||
}
|
||||
|
||||
void teleportNotPlayer(
|
||||
const MWWorld::Ptr& ptr, MWWorld::CellStore* destCell, const osg::Vec3f& pos, const osg::Vec3f& rot)
|
||||
void teleportNotPlayer(const MWWorld::Ptr& ptr, MWWorld::CellStore* destCell, const osg::Vec3f& pos,
|
||||
const osg::Vec3f& rot, bool placeOnGround)
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
const MWWorld::Class& cls = ptr.getClass();
|
||||
if (cls.isActor())
|
||||
cls.getCreatureStats(ptr).land(false);
|
||||
{
|
||||
auto& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
stats.land(false);
|
||||
stats.setTeleported(true);
|
||||
}
|
||||
MWWorld::Ptr newPtr = world->moveObject(ptr, destCell, pos);
|
||||
world->rotateObject(newPtr, rot, MWBase::RotationFlag_none);
|
||||
if (placeOnGround)
|
||||
world->adjustPosition(newPtr, true);
|
||||
if (cls.isDoor())
|
||||
{ // Change "original position and rotation" because without it teleported animated doors don't work
|
||||
// properly.
|
||||
newPtr.getCellRef().setPosition(newPtr.getRefData().getPosition());
|
||||
}
|
||||
if (!newPtr.getRefData().isEnabled())
|
||||
world->enable(newPtr);
|
||||
}
|
||||
@ -343,38 +362,47 @@ namespace MWLua
|
||||
});
|
||||
};
|
||||
objectT["teleport"] = [removeFn, context](const GObject& object, const sol::object& cellOrName,
|
||||
const osg::Vec3f& pos, const sol::optional<osg::Vec3f>& optRot) {
|
||||
const osg::Vec3f& pos, const sol::object& options) {
|
||||
MWWorld::CellStore* cell = findCell(cellOrName, pos);
|
||||
MWWorld::Ptr ptr = object.ptr();
|
||||
int count = ptr.getRefData().getCount();
|
||||
if (count == 0)
|
||||
throw std::runtime_error("Object is either removed or already in the process of teleporting");
|
||||
osg::Vec3f rot = optRot ? *optRot : ptr.getRefData().getPosition().asRotationVec3();
|
||||
osg::Vec3f rot = ptr.getRefData().getPosition().asRotationVec3();
|
||||
bool placeOnGround = false;
|
||||
if (options.is<osg::Vec3f>())
|
||||
rot = options.as<osg::Vec3f>();
|
||||
else if (options != sol::nil)
|
||||
{
|
||||
sol::table t = LuaUtil::cast<sol::table>(options);
|
||||
rot = LuaUtil::getValueOrDefault(t["rotation"], rot);
|
||||
placeOnGround = LuaUtil::getValueOrDefault(t["onGround"], placeOnGround);
|
||||
}
|
||||
if (ptr.getContainerStore())
|
||||
{
|
||||
DelayedRemovalFn delayedRemovalFn = *removeFn(ptr, count);
|
||||
context.mLuaManager->addAction(
|
||||
[object, cell, pos, rot, count, delayedRemovalFn] {
|
||||
[object, cell, pos, rot, count, delayedRemovalFn, placeOnGround] {
|
||||
MWWorld::Ptr oldPtr = object.ptr();
|
||||
oldPtr.getRefData().setCount(count);
|
||||
MWWorld::Ptr newPtr = oldPtr.getClass().moveToCell(oldPtr, *cell);
|
||||
oldPtr.getRefData().setCount(0);
|
||||
newPtr.getRefData().disable();
|
||||
teleportNotPlayer(newPtr, cell, pos, rot);
|
||||
teleportNotPlayer(newPtr, cell, pos, rot, placeOnGround);
|
||||
delayedRemovalFn(oldPtr);
|
||||
},
|
||||
"TeleportFromContainerAction");
|
||||
}
|
||||
else if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
context.mLuaManager->addTeleportPlayerAction(
|
||||
[cell, pos, rot] { teleportPlayer(cell, pos, rot); });
|
||||
[cell, pos, rot, placeOnGround] { teleportPlayer(cell, pos, rot, placeOnGround); });
|
||||
else
|
||||
{
|
||||
ptr.getRefData().setCount(0);
|
||||
context.mLuaManager->addAction(
|
||||
[object, cell, pos, rot, count] {
|
||||
[object, cell, pos, rot, count, placeOnGround] {
|
||||
object.ptr().getRefData().setCount(count);
|
||||
teleportNotPlayer(object.ptr(), cell, pos, rot);
|
||||
teleportNotPlayer(object.ptr(), cell, pos, rot, placeOnGround);
|
||||
},
|
||||
"TeleportAction");
|
||||
}
|
||||
|
@ -1862,7 +1862,7 @@ namespace MWMechanics
|
||||
float scale = mPtr.getCellRef().getScale();
|
||||
|
||||
static const bool normalizeSpeed = Settings::Manager::getBool("normalise race speed", "Game");
|
||||
if (!normalizeSpeed && mPtr.getClass().isNpc())
|
||||
if (!normalizeSpeed && cls.isNpc())
|
||||
{
|
||||
const ESM::NPC* npc = mPtr.get<ESM::NPC>()->mBase;
|
||||
const ESM::Race* race = world->getStore().get<ESM::Race>().find(npc->mRace);
|
||||
@ -1870,6 +1870,12 @@ namespace MWMechanics
|
||||
scale *= weight;
|
||||
}
|
||||
|
||||
if (cls.isActor() && cls.getCreatureStats(mPtr).wasTeleported())
|
||||
{
|
||||
mSmoothedSpeed = osg::Vec2f();
|
||||
cls.getCreatureStats(mPtr).setTeleported(false);
|
||||
}
|
||||
|
||||
if (!cls.isActor())
|
||||
updateAnimQueue();
|
||||
else if (!cls.getCreatureStats(mPtr).isDead())
|
||||
|
@ -85,6 +85,8 @@ namespace MWMechanics
|
||||
// The difference between view direction and lower body direction.
|
||||
float mSideMovementAngle;
|
||||
|
||||
bool mTeleported = false;
|
||||
|
||||
private:
|
||||
std::multimap<int, int> mSummonedCreatures; // <Effect, ActorId>
|
||||
|
||||
@ -288,6 +290,9 @@ namespace MWMechanics
|
||||
|
||||
float getSideMovementAngle() const { return mSideMovementAngle; }
|
||||
void setSideMovementAngle(float angle) { mSideMovementAngle = angle; }
|
||||
|
||||
bool wasTeleported() const { return mTeleported; }
|
||||
void setTeleported(bool v) { mTeleported = v; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "../mwworld/worldmodel.hpp"
|
||||
|
||||
#include "../mwmechanics/actorutil.hpp"
|
||||
#include "../mwmechanics/creaturestats.hpp"
|
||||
|
||||
#include "interpretercontext.hpp"
|
||||
#include "ref.hpp"
|
||||
@ -389,10 +390,10 @@ namespace MWScript
|
||||
bool isPlayer = ptr == MWMechanics::getPlayer();
|
||||
auto world = MWBase::Environment::get().getWorld();
|
||||
auto worldModel = MWBase::Environment::get().getWorldModel();
|
||||
if (ptr.getClass().isActor())
|
||||
ptr.getClass().getCreatureStats(ptr).setTeleported(true);
|
||||
if (isPlayer)
|
||||
{
|
||||
world->getPlayer().setTeleported(true);
|
||||
}
|
||||
|
||||
MWWorld::CellStore* store = nullptr;
|
||||
try
|
||||
@ -463,10 +464,10 @@ namespace MWScript
|
||||
|
||||
bool isPlayer = ptr == MWMechanics::getPlayer();
|
||||
auto world = MWBase::Environment::get().getWorld();
|
||||
if (ptr.getClass().isActor())
|
||||
ptr.getClass().getCreatureStats(ptr).setTeleported(true);
|
||||
if (isPlayer)
|
||||
{
|
||||
world->getPlayer().setTeleported(true);
|
||||
}
|
||||
const ESM::ExteriorCellLocation cellIndex
|
||||
= ESM::positionToCellIndex(x, y, ESM::Cell::sDefaultWorldspaceId);
|
||||
|
||||
|
@ -47,7 +47,9 @@ namespace MWWorld
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
MWWorld::WorldModel* worldModel = MWBase::Environment::get().getWorldModel();
|
||||
actor.getClass().getCreatureStats(actor).land(actor == world->getPlayerPtr());
|
||||
auto& stats = actor.getClass().getCreatureStats(actor);
|
||||
stats.land(actor == world->getPlayerPtr());
|
||||
stats.setTeleported(true);
|
||||
|
||||
Ptr teleported;
|
||||
if (actor == world->getPlayerPtr())
|
||||
|
@ -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.
|
||||
|
@ -177,7 +177,13 @@
|
||||
-- @param #any cellOrName A cell to define the destination worldspace; can be either #Cell, or cell name, or an empty string (empty string means the default exterior worldspace).
|
||||
-- If the worldspace has multiple cells (i.e. an exterior), the destination cell is calculated using `position`.
|
||||
-- @param openmw.util#Vector3 position New position.
|
||||
-- @param openmw.util#Vector3 rotation (optional) New rotation. If missing, then the current rotation is used.
|
||||
-- @param #TeleportOptions options (optional) Either table @{#TeleportOptions} or @{openmw.util#Vector3} rotation.
|
||||
|
||||
---
|
||||
-- Either table with options or @{openmw.util#Vector3} rotation.
|
||||
-- @type TeleportOptions
|
||||
-- @field openmw.util#Vector3 rotation New rotation; if missing, then the current rotation is used.
|
||||
-- @field #boolean onGround If true, adjust destination position to the ground.
|
||||
|
||||
---
|
||||
-- Moves object into a container or an inventory. Enables if was disabled.
|
||||
@ -219,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