diff --git a/game/engines/default/engine/generator/map/Forest.lua b/game/engines/default/engine/generator/map/Forest.lua
index 320c66c36b5273692e349b55ffa08bc723d177e8..616bfd6662f52f6afd98a2fa137ac350cad58cdb 100644
--- a/game/engines/default/engine/generator/map/Forest.lua
+++ b/game/engines/default/engine/generator/map/Forest.lua
@@ -436,27 +436,35 @@ end
 
 --- Create the stairs inside the level
 function _M:makeStairsInside(lev, old_lev, spots)
-	-- Put down stairs
 	local dx, dy
-	if lev < self.zone.max_level or self.data.force_last_stair then
-		while true do
-			dx, dy = rng.range(1, self.map.w - 1), rng.range(1, self.map.h - 1)
-			if not self.map:checkEntity(dx, dy, Map.TERRAIN, "block_move") and not self.map.room_map[dx][dy].special then
-				self.map(dx, dy, Map.TERRAIN, self:resolve("down"))
-				self.map.room_map[dx][dy].special = "exit"
-				break
+	if self.forced_down then
+		dx, dy = self.forced_down.x, self.forced_down.y
+	else
+		-- Put down stairs
+		if lev < self.zone.max_level or self.data.force_last_stair then
+			while true do
+				dx, dy = rng.range(1, self.map.w - 1), rng.range(1, self.map.h - 1)
+				if not self.map:checkEntity(dx, dy, Map.TERRAIN, "block_move") and not self.map.room_map[dx][dy].special then
+					self.map(dx, dy, Map.TERRAIN, self:resolve("down"))
+					self.map.room_map[dx][dy].special = "exit"
+					break
+				end
 			end
 		end
 	end
 
 	-- Put up stairs
 	local ux, uy
-	while true do
-		ux, uy = rng.range(1, self.map.w - 1), rng.range(1, self.map.h - 1)
-		if not self.map:checkEntity(ux, uy, Map.TERRAIN, "block_move") and not self.map.room_map[ux][uy].special then
-			self.map(ux, uy, Map.TERRAIN, self:resolve("up"))
-			self.map.room_map[ux][uy].special = "exit"
-			break
+	if self.forced_up then
+		ux, uy = self.forced_up.x, self.forced_up.y
+	else
+		while true do
+			ux, uy = rng.range(1, self.map.w - 1), rng.range(1, self.map.h - 1)
+			if not self.map:checkEntity(ux, uy, Map.TERRAIN, "block_move") and not self.map.room_map[ux][uy].special then
+				self.map(ux, uy, Map.TERRAIN, self:resolve("up"))
+				self.map.room_map[ux][uy].special = "exit"
+				break
+			end
 		end
 	end
 
@@ -467,35 +475,43 @@ end
 function _M:makeStairsSides(lev, old_lev, sides, spots)
 	-- Put down stairs
 	local dx, dy
-	if lev < self.zone.max_level or self.data.force_last_stair then
-		while true do
-			if     sides[2] == 4 then dx, dy = 0, rng.range(0, self.map.h - 1)
-			elseif sides[2] == 6 then dx, dy = self.map.w - 1, rng.range(0, self.map.h - 1)
-			elseif sides[2] == 8 then dx, dy = rng.range(0, self.map.w - 1), 0
-			elseif sides[2] == 2 then dx, dy = rng.range(0, self.map.w - 1), self.map.h - 1
-			end
+	if self.forced_down then
+		dx, dy = self.forced_down.x, self.forced_down.y
+	else
+		if lev < self.zone.max_level or self.data.force_last_stair then
+			while true do
+				if     sides[2] == 4 then dx, dy = 0, rng.range(0, self.map.h - 1)
+				elseif sides[2] == 6 then dx, dy = self.map.w - 1, rng.range(0, self.map.h - 1)
+				elseif sides[2] == 8 then dx, dy = rng.range(0, self.map.w - 1), 0
+				elseif sides[2] == 2 then dx, dy = rng.range(0, self.map.w - 1), self.map.h - 1
+				end
 
-			if not self.map.room_map[dx][dy].special then
-				self.map(dx, dy, Map.TERRAIN, self:resolve("down"))
-				self.map.room_map[dx][dy].special = "exit"
-				break
+				if not self.map.room_map[dx][dy].special then
+					self.map(dx, dy, Map.TERRAIN, self:resolve("down"))
+					self.map.room_map[dx][dy].special = "exit"
+					break
+				end
 			end
 		end
 	end
 
 	-- Put up stairs
 	local ux, uy
-	while true do
-		if     sides[1] == 4 then ux, uy = 0, rng.range(0, self.map.h - 1)
-		elseif sides[1] == 6 then ux, uy = self.map.w - 1, rng.range(0, self.map.h - 1)
-		elseif sides[1] == 8 then ux, uy = rng.range(0, self.map.w - 1), 0
-		elseif sides[1] == 2 then ux, uy = rng.range(0, self.map.w - 1), self.map.h - 1
-		end
+	if self.forced_up then
+		ux, uy = self.forced_up.x, self.forced_up.y
+	else
+		while true do
+			if     sides[1] == 4 then ux, uy = 0, rng.range(0, self.map.h - 1)
+			elseif sides[1] == 6 then ux, uy = self.map.w - 1, rng.range(0, self.map.h - 1)
+			elseif sides[1] == 8 then ux, uy = rng.range(0, self.map.w - 1), 0
+			elseif sides[1] == 2 then ux, uy = rng.range(0, self.map.w - 1), self.map.h - 1
+			end
 
-		if not self.map.room_map[ux][uy].special then
-			self.map(ux, uy, Map.TERRAIN, self:resolve("up"))
-			self.map.room_map[ux][uy].special = "exit"
-			break
+			if not self.map.room_map[ux][uy].special then
+				self.map(ux, uy, Map.TERRAIN, self:resolve("up"))
+				self.map.room_map[ux][uy].special = "exit"
+				break
+			end
 		end
 	end
 
diff --git a/game/engines/default/engine/generator/map/RoomsLoader.lua b/game/engines/default/engine/generator/map/RoomsLoader.lua
index 1227a0af752f370aea8d2afeb822514117f31a91..8050a1cbf92ffcb2165bdd89df2a36edf2445cf4 100644
--- a/game/engines/default/engine/generator/map/RoomsLoader.lua
+++ b/game/engines/default/engine/generator/map/RoomsLoader.lua
@@ -71,7 +71,7 @@ function _M:tmxLoadRoom(file, basefile)
 
 	local g = {}
 	local t = {}
-	local openids = {}
+	local openids, starts, ends = {}, {}, {}
 	local map = lom.parse(data)
 	local mapprops = {}
 	if map:findOne("properties") then mapprops = map:findOne("properties"):findAllAttrs("property", "name", "value") end
@@ -101,6 +101,8 @@ function _M:tmxLoadRoom(file, basefile)
 			local data_id = tile:findOne("property", "name", "data_id")
 			local custom = tile:findOne("property", "name", "custom")
 			local open = tile:findOne("property", "name", "open")
+			local is_start = tile:findOne("property", "name", "start")
+			local is_end = tile:findOne("property", "name", "stop") or tile:findOne("property", "name", "end")
 			if id then
 				t[tid] = id.attr.value
 			elseif data_id then
@@ -110,6 +112,8 @@ function _M:tmxLoadRoom(file, basefile)
 				t[tid] = ret
 			end
 			openids[tid] = open
+			starts[tid] = is_start
+			ends[tid] = is_end
 		end
 	end
 
@@ -155,7 +159,7 @@ function _M:tmxLoadRoom(file, basefile)
 			local x, y = 1, 1
 			while i <= #data do
 				gid, i = struct.unpack("<I4", data, i)
-				populate(x, y, {[layername] = gid, can_open=openids[gid]}, gid)
+				populate(x, y, {[layername] = gid, can_open=openids[gid], is_start=starts[gid], is_end=ends[gid]}, gid)
 				x = x + 1
 				if x > w then x = 1 y = y + 1 end
 			end
@@ -164,7 +168,7 @@ function _M:tmxLoadRoom(file, basefile)
 			local x, y = 1, 1
 			for i, gid in ipairs(data) do
 				gid = tonumber(gid)
-				populate(x, y, {[layername] = gid, can_open=openids[gid]}, gid)
+				populate(x, y, {[layername] = gid, can_open=openids[gid], is_start=starts[gid], is_end=ends[gid]}, gid)
 				x = x + 1
 				if x > w then x = 1 y = y + 1 end
 			end
@@ -173,7 +177,7 @@ function _M:tmxLoadRoom(file, basefile)
 			local x, y = 1, 1
 			for i, tile in ipairs(data) do
 				local gid = tonumber(tile.attr.gid)
-				populate(x, y, {[layername] = gid, can_open=openids[gid]}, gid)
+				populate(x, y, {[layername] = gid, can_open=openids[gid], is_start=starts[gid], is_end=ends[gid]}, gid)
 				x = x + 1
 				if x > w then x = 1 y = y + 1 end
 			end
@@ -227,6 +231,16 @@ function _M:tmxLoadRoom(file, basefile)
 					gen.map.room_map[i-1+x][j-1+y].room = nil
 					gen.map.room_map[i-1+x][j-1+y].can_open = true
 				end
+				if c.is_start then
+					gen.forced_up = {x=i-1+x, y=j-1+y}
+					gen.map.forced_up = {x=i-1+x, y=j-1+y}
+					gen.map.room_map[i-1+x][j-1+y].special = "exit"
+				end
+				if c.is_end then
+					gen.forced_down = {x=i-1+x, y=j-1+y}
+					gen.map.forced_down = {x=i-1+x, y=j-1+y}
+					gen.map.room_map[i-1+x][j-1+y].special = "exit"
+				end
 
 				if c.grid then
 					local g = gen:resolve(t[c.grid], nil, true)
diff --git a/game/modules/tome/data/talents/chronomancy/chronomancer.lua b/game/modules/tome/data/talents/chronomancy/chronomancer.lua
index 22a1f8b2453c176526fce7f409cd30218be714e9..7316a90ea37dc66280cac6f682382419268cccf6 100644
--- a/game/modules/tome/data/talents/chronomancy/chronomancer.lua
+++ b/game/modules/tome/data/talents/chronomancy/chronomancer.lua
@@ -293,7 +293,7 @@ makeParadoxClone = function(self, target, duration, alt_nodes)
 
 	-- Don't copy certain fields from the target
 	alt_nodes = alt_nodes or {}
-	alt_nodes[target:getInven("INVEN")] = false -- Skip main inventory; equipped items are still copied
+	if target:getInven("INVEN") then alt_nodes[target:getInven("INVEN")] = false end -- Skip main inventory; equipped items are still copied
 	alt_nodes.quests = false
 	alt_nodes.random_escort_levels = false
 	alt_nodes.achievements = false
@@ -325,7 +325,6 @@ makeParadoxClone = function(self, target, duration, alt_nodes)
 	local m = target:cloneCustom(alt_nodes)
 	
 	-- Basic setup
-	m.dead = false
 	m.no_drops = true
 	m.keep_inven_on_death = false
 	m.faction = target.faction