Index: trunk/src/lua/lua_area.cc
===================================================================
--- trunk/src/lua/lua_area.cc	(revision 177)
+++ trunk/src/lua/lua_area.cc	(revision 179)
@@ -11,5 +11,5 @@
 #include "nv/random.hh"
 
-#define NLUA_AREA_METATABLE "area"
+static const char* NLUA_AREA_METATABLE = "area";
 
 bool nlua_is_area( lua_State* L, int index )
@@ -102,5 +102,5 @@
 	else
 	{
-		luaL_getmetafield( L, 1, "__base" );
+		luaL_getmetafield( L, 1, "__functions" );
 		lua_pushvalue( L, 2 );
 		lua_rawget( L, -2 );
Index: trunk/src/lua/lua_map_area.cc
===================================================================
--- trunk/src/lua/lua_map_area.cc	(revision 179)
+++ trunk/src/lua/lua_map_area.cc	(revision 179)
@@ -0,0 +1,200 @@
+// Copyright (C) 2012-2013 ChaosForge / Kornel Kisielewicz
+// http://chaosforge.org/
+//
+// This file is part of NV Libraries.
+// For conditions of distribution and use, see copyright notice in nv.hh
+
+#include "nv/lua/lua_map_area.hh"
+#include "nv/flags.hh"
+#include "nv/lua/lua_area.hh"
+#include "nv/lua/lua_glm.hh"
+#include "nv/lua/lua_raw.hh"
+
+static const char* NLUA_MAP_AREA_METATABLE = "map_area";
+
+typedef nv::flags<512> cell_set;
+
+nv::uint32 nlua_to_cell_id( lua_State* L, int index, nv::map_area* map )
+{
+	if ( lua_type( L, index ) == LUA_TSTRING ) 
+		return map->string_to_id( lua_tostring( L, index ) );
+	else
+		return (nv::uint32)lua_tointeger( L, index );
+}
+
+cell_set nlua_to_cell_set( lua_State* L, int index, nv::map_area* map )
+{
+	cell_set result;
+	switch ( lua_type( L, index ) )
+	{
+	case LUA_TTABLE :	
+		{
+			lua_pushnil( L );
+			while ( lua_next( L, index ) != 0 )
+			{
+				if ( lua_type( L, -1 ) == LUA_TSTRING )
+					result.set( map->string_to_id( lua_tostring( L, -1 ) ), true );
+				else
+					result.set( lua_tointeger( L, -1 ), true );
+				lua_pop( L, 1 );
+			}
+		} break;
+	case LUA_TSTRING : result.set( map->string_to_id( lua_tostring( L, index ) ), true ); break;
+	case LUA_TNUMBER : result.set( lua_tointeger( L, index ), true ); break;
+	}
+	return result;
+}
+
+bool nlua_is_map_area( lua_State* L, int index )
+{
+	return luaL_testudata( L, index, NLUA_MAP_AREA_METATABLE ) != 0;
+}
+
+nv::map_area* nlua_to_map_area( lua_State* L, int index )
+{
+	return *(nv::map_area**)luaL_checkudata( L, index, NLUA_MAP_AREA_METATABLE );
+}
+
+void nlua_push_map_area( lua_State* L, nv::map_area* c )
+{
+	nv::map_area** pm = (nv::map_area**) (lua_newuserdata(L, sizeof(nv::map_area*)));
+	*pm = c;
+	luaL_getmetatable( L, NLUA_MAP_AREA_METATABLE );
+	lua_setmetatable( L, -2 );
+}
+
+static int nlua_map_area_tostring( lua_State* L )
+{
+	lua_pushstring( L, "map_area" );
+	return 1;
+}
+
+static int nlua_map_area_gc( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	if ( ma != nullptr )
+	{
+		delete ma;
+	}
+	return 0;
+}
+
+static int nlua_map_area_get_area( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	nlua_push_area( L, ma->get_rectangle() );
+	return 1;
+}
+
+static int nlua_map_area_get_shift( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	nlua_push_coord( L, ma->get_shift() );
+	return 1;
+}
+
+static int nlua_map_area_get_size( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	nlua_push_coord( L, ma->get_size() );
+	return 1;
+}
+
+static int nlua_map_area_get_cell( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	lua_pushstring( L, ma->id_to_string( ma->get_cell( nlua_to_coord( L, 2 ) ) ).c_str() );
+	return 1;
+}
+
+static int nlua_map_area_set_cell( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	ma->set_cell( nlua_to_coord( L, 2 ), nlua_to_cell_id( L, 3, ma ) );
+	return 0;
+}
+
+static int nlua_map_area_raw_get_cell( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	lua_pushinteger( L, ma->get_cell( nlua_to_coord( L, 2 ) ) );
+	return 1;
+}
+
+static int nlua_map_area_raw_set_cell( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	ma->set_cell( nlua_to_coord( L, 2 ), lua_tointeger( L, 3 ) );
+	return 0;
+}
+
+static int nlua_map_area_index( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	if ( lua_type( L, 1 ) == LUA_TSTRING )
+	{
+		luaL_getmetafield( L, 1, "__functions" );
+		lua_pushvalue( L, 2 );
+		lua_rawget( L, -2 );
+	}
+	else
+	{
+		lua_pushinteger( L, ma->get_cell( nlua_to_coord( L, 2 ) ) );
+	}
+	return 1;
+}
+
+static int nlua_map_area_newindex( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	ma->set_cell( nlua_to_coord( L, 2 ), lua_tointeger( L, 3 ) );
+	return 0;
+}
+
+static int nlua_map_area_new_sub_area( lua_State* L )
+{
+	nv::map_area* ma = nlua_to_map_area( L, 1 );
+	nlua_push_map_area( L, ma->create_sub_area( nlua_to_area( L, 2 ) ) );
+	return 1;
+}
+
+static const luaL_Reg nlua_map_area_f[] = {
+	{ "get_area",     nlua_map_area_get_area },
+	{ "get_shift",    nlua_map_area_get_shift },
+	{ "get_size",     nlua_map_area_get_size },
+	{ "get_cell",     nlua_map_area_get_cell },
+	{ "set_cell",     nlua_map_area_set_cell },
+	{ "raw_get_cell", nlua_map_area_raw_get_cell },
+	{ "raw_set_cell", nlua_map_area_raw_set_cell },
+	{ "new_sub_area", nlua_map_area_new_sub_area },
+	{NULL, NULL}
+};
+
+static const luaL_Reg nlua_map_area_mt[] = {
+	{ "__newindex", nlua_map_area_newindex },
+	{ "__index",    nlua_map_area_index },
+	{ "__tostring", nlua_map_area_tostring },
+	{ "__gc",       nlua_map_area_gc },
+	{NULL, NULL}
+};
+
+int luaopen_map_area( lua_State * L )
+{
+	luaL_newmetatable( L, NLUA_MAP_AREA_METATABLE );
+	nlua_register( L, nlua_map_area_mt, -1 );
+	lua_createtable( L, 0, 0 );
+	nlua_register( L, nlua_map_area_f, -1 );
+	lua_setfield(L, -2, "__functions" );
+	lua_pop( L, 1 );
+	return 0;
+}
+
+void nlua_register_map_area_interface( lua_State* L, int index )
+{
+	nlua_register( L, nlua_map_area_f, index );
+}
+
+void nlua_register_map_area( lua_State* L )
+{
+	luaopen_map_area(L);
+}
