diff --git a/apps/openmw-mp/Script/Functions/World.cpp b/apps/openmw-mp/Script/Functions/World.cpp
index ba7dba1a5..9147488b3 100644
--- a/apps/openmw-mp/Script/Functions/World.cpp
+++ b/apps/openmw-mp/Script/Functions/World.cpp
@@ -229,11 +229,6 @@ void WorldFunctions::SetObjectState(bool objectState) noexcept
     tempWorldObject.objectState = objectState;
 }
 
-void WorldFunctions::SetObjectDoorState(int doorState) noexcept
-{
-    tempWorldObject.doorState = doorState;
-}
-
 void WorldFunctions::SetObjectLockLevel(int lockLevel) noexcept
 {
     tempWorldObject.lockLevel = lockLevel;
@@ -263,6 +258,34 @@ void WorldFunctions::SetObjectRotation(double x, double y, double z) noexcept
     tempWorldObject.position.rot[2] = z;
 }
 
+void WorldFunctions::SetObjectDoorState(int doorState) noexcept
+{
+    tempWorldObject.doorState = doorState;
+}
+
+void WorldFunctions::SetObjectDoorTeleportState(bool teleportState) noexcept
+{
+    tempWorldObject.teleportState = teleportState;
+}
+
+void WorldFunctions::SetObjectDoorDestinationCell(const char* cellDescription) noexcept
+{
+    tempWorldObject.destinationCell = Utils::getCellFromDescription(cellDescription);
+}
+
+void WorldFunctions::SetObjectDoorDestinationPosition(double x, double y, double z) noexcept
+{
+    tempWorldObject.destinationPosition.pos[0] = x;
+    tempWorldObject.destinationPosition.pos[1] = y;
+    tempWorldObject.destinationPosition.pos[2] = z;
+}
+
+void WorldFunctions::SetObjectDoorDestinationRotation(double x, double z) noexcept
+{
+    tempWorldObject.destinationPosition.rot[0] = x;
+    tempWorldObject.destinationPosition.rot[2] = z;
+}
+
 void WorldFunctions::SetPlayerAsObject(unsigned short pid) noexcept
 {
     Player *player;
@@ -392,6 +415,16 @@ void WorldFunctions::SendDoorState(bool broadcast) noexcept
         packet->Send(true);
 }
 
+void WorldFunctions::SendDoorDestination(bool broadcast) noexcept
+{
+    mwmp::WorldPacket *packet = mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_DOOR_DESTINATION);
+    packet->setEvent(&writeEvent);
+    packet->Send(false);
+
+    if (broadcast)
+        packet->Send(true);
+}
+
 void WorldFunctions::SendContainer(bool broadcast, bool useLastReadEvent) noexcept
 {
     mwmp::WorldPacket *packet = mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONTAINER);
diff --git a/apps/openmw-mp/Script/Functions/World.hpp b/apps/openmw-mp/Script/Functions/World.hpp
index 95d8af7cd..2ba777dee 100644
--- a/apps/openmw-mp/Script/Functions/World.hpp
+++ b/apps/openmw-mp/Script/Functions/World.hpp
@@ -47,12 +47,18 @@
     {"SetObjectGoldValue",                    WorldFunctions::SetObjectGoldValue},\
     {"SetObjectScale",                        WorldFunctions::SetObjectScale},\
     {"SetObjectState",                        WorldFunctions::SetObjectState},\
-    {"SetObjectDoorState",                    WorldFunctions::SetObjectDoorState},\
     {"SetObjectLockLevel",                    WorldFunctions::SetObjectLockLevel},\
     {"SetObjectDisarmState",                  WorldFunctions::SetObjectDisarmState},\
     {"SetObjectMasterState",                  WorldFunctions::SetObjectMasterState},\
     {"SetObjectPosition",                     WorldFunctions::SetObjectPosition},\
     {"SetObjectRotation",                     WorldFunctions::SetObjectRotation},\
+    \
+    {"SetObjectDoorState",                    WorldFunctions::SetObjectDoorState},\
+    {"SetObjectDoorTeleportState",            WorldFunctions::SetObjectDoorTeleportState},\
+    {"SetObjectDoorDestinationCell",          WorldFunctions::SetObjectDoorDestinationCell},\
+    {"SetObjectDoorDestinationPosition",      WorldFunctions::SetObjectDoorDestinationPosition},\
+    {"SetObjectDoorDestinationRotation",      WorldFunctions::SetObjectDoorDestinationRotation},\
+    \
     {"SetPlayerAsObject",                     WorldFunctions::SetPlayerAsObject},\
     \
     {"SetContainerItemRefId",                 WorldFunctions::SetContainerItemRefId},\
@@ -73,6 +79,7 @@
     {"SendObjectScale",                       WorldFunctions::SendObjectScale},\
     {"SendObjectState",                       WorldFunctions::SendObjectState},\
     {"SendDoorState",                         WorldFunctions::SendDoorState},\
+    {"SendDoorDestination",                   WorldFunctions::SendDoorDestination},\
     {"SendContainer",                         WorldFunctions::SendContainer},\
     {"SendConsoleCommand",                    WorldFunctions::SendConsoleCommand},\
     \
@@ -80,7 +87,7 @@
     {"SetMonth",                              WorldFunctions::SetMonth},\
     {"SetDay",                                WorldFunctions::SetDay}
 
-class           WorldFunctions
+class WorldFunctions
 {
 public:
 
@@ -456,16 +463,6 @@ public:
     */
     static void SetObjectState(bool objectState) noexcept;
 
-    /**
-    * \brief Set the door state of the temporary world object stored on the server.
-    *
-    * Doors are open or closed based on their door state.
-    *
-    * \param doorState The door state.
-    * \return void
-    */
-    static void SetObjectDoorState(int doorState) noexcept;
-
     /**
     * \brief Set the lock level of the temporary world object stored on the server.
     *
@@ -513,6 +510,60 @@ public:
     */
     static void SetObjectRotation(double x, double y, double z) noexcept;
 
+    /**
+    * \brief Set the door state of the temporary world object stored on the server.
+    *
+    * Doors are open or closed based on their door state.
+    *
+    * \param doorState The door state.
+    * \return void
+    */
+    static void SetObjectDoorState(int doorState) noexcept;
+
+    /**
+    * \brief Set the teleport state of the temporary world object stored on the server.
+    *
+    * If a door's teleport state is true, interacting with the door teleports a player to its
+    * destination. If it's false, it opens and closes like a regular door.
+    *
+    * \param teleportState The teleport state.
+    * \return void
+    */
+    static void SetObjectDoorTeleportState(bool teleportState) noexcept;
+
+    /**
+    * \brief Set the door destination cell of the temporary world object stored on the server.
+    *
+    * The cell is determined to be an exterior cell if it fits the pattern of a number followed
+    * by a comma followed by another number.
+    *
+    * \param cellDescription The description of the cell.
+    * \return void
+    */
+    static void SetObjectDoorDestinationCell(const char* cellDescription) noexcept;
+
+    /**
+    * \brief Set the door destination position of the temporary world object stored on the server.
+    *
+    * \param x The X position.
+    * \param y The Y position.
+    * \param z The Z position.
+    * \return void
+    */
+    static void SetObjectDoorDestinationPosition(double x, double y, double z) noexcept;
+
+    /**
+    * \brief Set the door destination rotation of the temporary world object stored on the server.
+    *
+    * Note: Because this sets the rotation a player will have upon using the door, and rotation
+    *       on the Y axis has no effect on players, the Y value has been omitted as an argument.
+    *
+    * \param x The X rotation.
+    * \param z The Z rotation.
+    * \return void
+    */
+    static void SetObjectDoorDestinationRotation(double x, double z) noexcept;
+
     /**
     * \brief Set a player as the object in the temporary world object stored on the server.
     *        Currently only used for ConsoleCommand packets.
@@ -670,6 +721,16 @@ public:
     */
     static void SendDoorState(bool broadcast = false) noexcept;
 
+    /**
+    * \brief Send a DoorDestination packet.
+    *
+    * \param broadcast Whether this packet should be sent only to the player for whom the current
+    *                  event was initialized or to everyone on the server.
+    *
+    * \return void
+    */
+    static void SendDoorDestination(bool broadcast = false) noexcept;
+
     /**
     * \brief Send a Container packet.
     *
diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt
index a4e932eb5..ddd555a77 100644
--- a/apps/openmw/CMakeLists.txt
+++ b/apps/openmw/CMakeLists.txt
@@ -124,12 +124,12 @@ add_openmw_dir (mwmp/processors/player ProcessorChatMessage ProcessorGUIMessageB
     ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic
     )
 
-add_openmw_dir (mwmp/processors/world BaseObjectProcessor ProcessorConsoleCommand ProcessorContainer ProcessorDoorState
-    ProcessorMusicPlay ProcessorVideoPlay ProcessorObjectAnimPlay ProcessorObjectAttach ProcessorObjectCollision
-    ProcessorObjectDelete ProcessorObjectLock ProcessorObjectMove ProcessorObjectPlace ProcessorObjectReset
-    ProcessorObjectRotate ProcessorObjectScale ProcessorObjectSpawn ProcessorObjectState ProcessorObjectTrap
-    ProcessorScriptLocalShort ProcessorScriptLocalFloat ProcessorScriptMemberShort ProcessorScriptMemberFloat
-    ProcessorScriptGlobalShort ProcessorScriptGlobalFloat
+add_openmw_dir (mwmp/processors/world BaseObjectProcessor ProcessorConsoleCommand ProcessorContainer ProcessorDoorDestination
+    ProcessorDoorState ProcessorMusicPlay ProcessorVideoPlay ProcessorObjectAnimPlay ProcessorObjectAttach 
+    ProcessorObjectCollision ProcessorObjectDelete ProcessorObjectLock ProcessorObjectMove ProcessorObjectPlace 
+    ProcessorObjectReset ProcessorObjectRotate ProcessorObjectScale ProcessorObjectSpawn ProcessorObjectState 
+    ProcessorObjectTrap ProcessorScriptLocalShort ProcessorScriptLocalFloat ProcessorScriptMemberShort 
+    ProcessorScriptMemberFloat ProcessorScriptGlobalShort ProcessorScriptGlobalFloat
     )
 
 # Main executable
diff --git a/apps/openmw/mwmp/WorldEvent.cpp b/apps/openmw/mwmp/WorldEvent.cpp
index 03afd6317..30443a244 100644
--- a/apps/openmw/mwmp/WorldEvent.cpp
+++ b/apps/openmw/mwmp/WorldEvent.cpp
@@ -566,6 +566,34 @@ void WorldEvent::activateDoors(MWWorld::CellStore* cellStore)
     }
 }
 
+void WorldEvent::setDoorDestinations(MWWorld::CellStore* cellStore)
+{
+    for (const auto &worldObject : worldObjects)
+    {
+        LOG_APPEND(Log::LOG_VERBOSE, "- cellRef: %s, %i, %i", worldObject.refId.c_str(), worldObject.refNumIndex, worldObject.mpNum);
+
+        MWWorld::Ptr ptrFound = cellStore->searchExact(worldObject.refNumIndex, worldObject.mpNum);
+
+        if (ptrFound)
+        {
+            LOG_APPEND(Log::LOG_VERBOSE, "-- Found %s, %i, %i", ptrFound.getCellRef().getRefId().c_str(),
+                ptrFound.getCellRef().getRefNum(), ptrFound.getCellRef().getMpNum());
+
+            ptrFound.getCellRef().setTeleport(worldObject.teleportState);
+
+            if (worldObject.teleportState)
+            {
+                ptrFound.getCellRef().setDoorDest(worldObject.destinationPosition);
+
+                if (worldObject.destinationCell.isExterior())
+                    ptrFound.getCellRef().setDestCell("");
+                else
+                    ptrFound.getCellRef().setDestCell(worldObject.destinationCell.getDescription());
+            }
+        }
+    }
+}
+
 void WorldEvent::runConsoleCommands(MWWorld::CellStore* cellStore)
 {
     MWBase::WindowManager *windowManager = MWBase::Environment::get().getWindowManager();
diff --git a/apps/openmw/mwmp/WorldEvent.hpp b/apps/openmw/mwmp/WorldEvent.hpp
index 7ef4e7dbf..a8e15313c 100644
--- a/apps/openmw/mwmp/WorldEvent.hpp
+++ b/apps/openmw/mwmp/WorldEvent.hpp
@@ -35,6 +35,7 @@ namespace mwmp
         void rotateObjects(MWWorld::CellStore* cellStore);
         void animateObjects(MWWorld::CellStore* cellStore);
         void activateDoors(MWWorld::CellStore* cellStore);
+        void setDoorDestinations(MWWorld::CellStore* cellStore);
         void runConsoleCommands(MWWorld::CellStore* cellStore);
 
         void setLocalShorts(MWWorld::CellStore* cellStore);
diff --git a/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp b/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp
index 8a671696d..5ecb4fc53 100644
--- a/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp
+++ b/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp
@@ -17,7 +17,7 @@ namespace mwmp
         {
             BaseObjectProcessor::Do(packet, event);
 
-            //event.setDoorDestinations(ptrCellStore);
+            event.setDoorDestinations(ptrCellStore);
         }
     };
 }
diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp
index 952d1cde9..602248bb1 100644
--- a/apps/openmw/mwworld/cellref.cpp
+++ b/apps/openmw/mwworld/cellref.cpp
@@ -56,16 +56,55 @@ namespace MWWorld
         return mCellRef.mTeleport;
     }
 
+    /*
+        Start of tes3mp addition
+
+        Make it possible to change the teleport state from elsewhere
+    */
+    void CellRef::setTeleport(bool teleportState)
+    {
+        mCellRef.mTeleport = teleportState;
+    }
+    /*
+        End of tes3mp addition
+    */
+
     ESM::Position CellRef::getDoorDest() const
     {
         return mCellRef.mDoorDest;
     }
 
+    /*
+        Start of tes3mp addition
+
+        Make it possible to change the destination position from elsewhere
+    */
+    void CellRef::setDoorDest(const ESM::Position& position)
+    {
+        mCellRef.mDoorDest = position;
+    }
+    /*
+        End of tes3mp addition
+    */
+
     std::string CellRef::getDestCell() const
     {
         return mCellRef.mDestCell;
     }
 
+    /*
+        Start of tes3mp addition
+
+        Make it possible to change the destination cell from elsewhere
+    */
+    void CellRef::setDestCell(const std::string& cellDescription)
+    {
+        mCellRef.mDestCell = cellDescription;
+    }
+    /*
+        End of tes3mp addition
+    */
+
     float CellRef::getScale() const
     {
         return mCellRef.mScale;
diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp
index 790b589bc..18f8a7165 100644
--- a/apps/openmw/mwworld/cellref.hpp
+++ b/apps/openmw/mwworld/cellref.hpp
@@ -58,12 +58,42 @@ namespace MWWorld
         // if it should open through animation.
         bool getTeleport() const;
 
+        /*
+            Start of tes3mp addition
+
+            Make it possible to change the teleport state from elsewhere
+        */
+        void setTeleport(bool teleportState);
+        /*
+            End of tes3mp addition
+        */
+
         // Teleport location for the door, if this is a teleporting door.
         ESM::Position getDoorDest() const;
 
+        /*
+            Start of tes3mp addition
+
+            Make it possible to change the destination position from elsewhere
+        */
+        void setDoorDest(const ESM::Position& position);
+        /*
+            End of tes3mp addition
+        */
+
         // Destination cell for doors (optional)
         std::string getDestCell() const;
 
+        /*
+            Start of tes3mp addition
+
+            Make it possible to change the destination cell from elsewhere
+        */
+        void setDestCell(const std::string& cellDescription);
+        /*
+            End of tes3mp addition
+        */
+
         // Scale applied to mesh
         float getScale() const;
         void setScale(float scale);
diff --git a/components/openmw-mp/Base/BaseEvent.hpp b/components/openmw-mp/Base/BaseEvent.hpp
index b2a66c9fd..6229b94cc 100644
--- a/components/openmw-mp/Base/BaseEvent.hpp
+++ b/components/openmw-mp/Base/BaseEvent.hpp
@@ -35,10 +35,14 @@ namespace mwmp
         ESM::Position position;
 
         bool objectState;
-        int doorState;
         int lockLevel;
         float scale;
 
+        int doorState;
+        bool teleportState;
+        ESM::Cell destinationCell;
+        ESM::Position destinationPosition;
+
         std::string filename;
         bool allowSkipping;
 
diff --git a/components/openmw-mp/Packets/World/PacketDoorDestination.cpp b/components/openmw-mp/Packets/World/PacketDoorDestination.cpp
index 41f3c2764..827d65e40 100644
--- a/components/openmw-mp/Packets/World/PacketDoorDestination.cpp
+++ b/components/openmw-mp/Packets/World/PacketDoorDestination.cpp
@@ -12,5 +12,16 @@ PacketDoorDestination::PacketDoorDestination(RakNet::RakPeerInterface *peer) : W
 void PacketDoorDestination::Object(WorldObject &worldObject, bool send)
 {
     WorldPacket::Object(worldObject, send);
-    // Placeholder
+
+    RW(worldObject.teleportState, send);
+
+    if (worldObject.teleportState)
+    {
+        RW(worldObject.destinationCell.mData, send, 1);
+        RW(worldObject.destinationCell.mName, send, 1);
+
+        RW(worldObject.destinationPosition.pos, send, 1);
+        RW(worldObject.destinationPosition.rot[0], send, 1);
+        RW(worldObject.destinationPosition.rot[2], send, 1);
+    }
 }