diff --git a/apps/openmw/mwlua/objectbindings.cpp b/apps/openmw/mwlua/objectbindings.cpp index 0906c44a53..55f18a01ac 100644 --- a/apps/openmw/mwlua/objectbindings.cpp +++ b/apps/openmw/mwlua/objectbindings.cpp @@ -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; @@ -78,11 +79,16 @@ namespace MWLua 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(); @@ -94,6 +100,8 @@ namespace MWLua } MWWorld::Ptr newPtr = world->moveObject(ptr, destCell, pos); world->rotateObject(newPtr, rot, MWBase::RotationFlag_none); + if (placeOnGround) + world->adjustPosition(newPtr, true); if (!newPtr.getRefData().isEnabled()) world->enable(newPtr); } @@ -349,38 +357,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"); } diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 0312ba8706..a472b8ac88 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -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.