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.