diff --git a/src/lua_libs.h b/src/lua_libs.h
index 931cf62d0bc11901d303969d821dd30a30266e6c..6c9524dea9d56aacb3f0dc6f08e037727ca47bc7 100644
--- a/src/lua_libs.h
+++ b/src/lua_libs.h
@@ -38,6 +38,7 @@ extern lua_State *gL;
 #define META_SUBSECTOR "SUBSECTOR_T*"
 #define META_SECTOR "SECTOR_T*"
 #define META_FFLOOR "FFLOOR_T*"
+#define META_SEG "SEG_T*"
 #define META_MAPHEADER "MAPHEADER_T*"
 
 #define META_CVAR "CONSVAR_T*"
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index c512bf3c5292cdb1030209b6aca5277fded6dd9c..28561f34efba627d13eecafffee3c239dc57f122 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -185,6 +185,32 @@ static const char *const ffloor_opt[] = {
 	"alpha",
 	NULL};
 
+enum seg_e {
+	seg_valid = 0,
+	seg_v1,
+	seg_v2,
+	seg_side,
+	seg_offset,
+	seg_angle,
+	seg_sidedef,
+	seg_linedef,
+	seg_frontsector,
+	seg_backsector,
+};
+
+static const char *const seg_opt[] = {
+	"valid",
+	"v1",
+	"v2",
+	"side",
+	"offset",
+	"angle",
+	"sidedef",
+	"linedef",
+	"frontsector",
+	"backsector",
+	NULL};
+
 static const char *const array_opt[] ={"iterate",NULL};
 static const char *const valid_opt[] ={"valid",NULL};
 
@@ -818,6 +844,63 @@ static int vertex_num(lua_State *L)
 	return 1;
 }
 
+static int seg_get(lua_State *L)
+{
+	seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
+	enum seg_e field = luaL_checkoption(L, 2, seg_opt[0], seg_opt);
+
+	if (!seg)
+	{
+		if (field == seg_valid) {
+			lua_pushboolean(L, 0);
+			return 1;
+		}
+		return luaL_error(L, "accessed seg_t doesn't exist anymore.");
+	}
+
+	switch(field)
+	{
+	case seg_valid: // valid
+		lua_pushboolean(L, 1);
+		return 1;
+	case seg_v1:
+		LUA_PushUserdata(L, seg->v1, META_VERTEX);
+		return 1;
+	case seg_v2:
+		LUA_PushUserdata(L, seg->v2, META_VERTEX);
+		return 1;
+	case seg_side:
+		lua_pushinteger(L, seg->side);
+		return 1;
+	case seg_offset:
+		lua_pushfixed(L, seg->offset);
+		return 1;
+	case seg_angle:
+		lua_pushangle(L, seg->angle);
+		return 1;
+	case seg_sidedef:
+		LUA_PushUserdata(L, seg->sidedef, META_SIDE);
+		return 1;
+	case seg_linedef:
+		LUA_PushUserdata(L, seg->linedef, META_LINE);
+		return 1;
+	case seg_frontsector:
+		LUA_PushUserdata(L, seg->frontsector, META_SECTOR);
+		return 1;
+	case seg_backsector:
+		LUA_PushUserdata(L, seg->backsector, META_SECTOR);
+		return 1;
+	}
+	return 0;
+}
+
+static int seg_num(lua_State *L)
+{
+	seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
+	lua_pushinteger(L, seg-segs);
+	return 1;
+}
+
 static int lib_iterateSectors(lua_State *L)
 {
 	size_t i = 0;
@@ -1048,6 +1131,52 @@ static int lib_numvertexes(lua_State *L)
 	return 1;
 }
 
+static int lib_iterateSegs(lua_State *L)
+{
+	size_t i = 0;
+	if (lua_gettop(L) < 2)
+		return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'.");
+	lua_settop(L, 2);
+	lua_remove(L, 1); // state is unused.
+	if (!lua_isnil(L, 1))
+		i = (size_t)(*((seg_t **)luaL_checkudata(L, 1, META_SEG)) - segs)+1;
+	if (i < numsegs)
+	{
+		LUA_PushUserdata(L, &segs[i], META_SEG);
+		return 1;
+	}
+	return 0;
+}
+
+static int lib_getSeg(lua_State *L)
+{
+	int field;
+	lua_settop(L, 2);
+	lua_remove(L, 1); // dummy userdata table is unused.
+	if (lua_isnumber(L, 1))
+	{
+		size_t i = lua_tointeger(L, 1);
+		if (i >= numsegs)
+			return 0;
+		LUA_PushUserdata(L, &segs[i], META_SEG);
+		return 1;
+	}
+	field = luaL_checkoption(L, 1, NULL, array_opt);
+	switch(field)
+	{
+	case 0: // iterate
+		lua_pushcfunction(L, lib_iterateSegs);
+		return 1;
+	}
+	return 0;
+}
+
+static int lib_numsegs(lua_State *L)
+{
+	lua_pushinteger(L, numsegs);
+	return 1;
+}
+
 static int ffloor_get(lua_State *L)
 {
 	ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
@@ -1367,6 +1496,14 @@ int LUA_MapLib(lua_State *L)
 		lua_setfield(L, -2, "__newindex");
 	lua_pop(L, 1);
 
+	luaL_newmetatable(L, META_SEG);
+		lua_pushcfunction(L, seg_get);
+		lua_setfield(L, -2, "__index");
+
+		lua_pushcfunction(L, seg_num);
+		lua_setfield(L, -2, "__len");
+	lua_pop(L, 1);
+
 	luaL_newmetatable(L, META_MAPHEADER);
 		lua_pushcfunction(L, mapheaderinfo_get);
 		lua_setfield(L, -2, "__index");
@@ -1425,6 +1562,16 @@ int LUA_MapLib(lua_State *L)
 		lua_setmetatable(L, -2);
 	lua_setglobal(L, "vertexes");
 
+	lua_newuserdata(L, 0);
+		lua_createtable(L, 0, 2);
+			lua_pushcfunction(L, lib_getSeg);
+			lua_setfield(L, -2, "__index");
+
+			lua_pushcfunction(L, lib_numsegs);
+			lua_setfield(L, -2, "__len");
+		lua_setmetatable(L, -2);
+	lua_setglobal(L, "segs");
+
 	lua_newuserdata(L, 0);
 		lua_createtable(L, 0, 2);
 			lua_pushcfunction(L, lib_getMapheaderinfo);
diff --git a/src/lua_script.c b/src/lua_script.c
index acb306827ecf0687c8689fa1600ddd95dc52914b..621b7dfe48327e5d47c9cfe2d2896312b27c9072 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -455,6 +455,7 @@ enum
 	ARCH_SIDE,
 	ARCH_SUBSECTOR,
 	ARCH_SECTOR,
+	ARCH_SEG,
 	ARCH_MAPHEADER,
 
 	ARCH_TEND=0xFF,
@@ -474,6 +475,7 @@ static const struct {
 	{META_SIDE,     ARCH_SIDE},
 	{META_SUBSECTOR,ARCH_SUBSECTOR},
 	{META_SECTOR,   ARCH_SECTOR},
+	{META_SEG,      ARCH_SEG},
 	{META_MAPHEADER,   ARCH_MAPHEADER},
 	{NULL,          ARCH_NULL}
 };
@@ -664,6 +666,17 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 			}
 			break;
 		}
+		case ARCH_SEG:
+		{
+			seg_t *seg = *((seg_t **)lua_touserdata(gL, myindex));
+			if (!seg)
+				WRITEUINT8(save_p, ARCH_NULL);
+			else {
+				WRITEUINT8(save_p, ARCH_SEG);
+				WRITEUINT16(save_p, seg - segs);
+			}
+			break;
+		}
 		case ARCH_MAPHEADER:
 		{
 			mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex));
@@ -842,6 +855,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
 	case ARCH_SECTOR:
 		LUA_PushUserdata(gL, &sectors[READUINT16(save_p)], META_SECTOR);
 		break;
+	case ARCH_SEG:
+		LUA_PushUserdata(gL, &segs[READUINT16(save_p)], META_SEG);
+		break;
 	case ARCH_MAPHEADER:
 		LUA_PushUserdata(gL, &sectors[READUINT16(save_p)], META_MAPHEADER);
 		break;