All pastes #802653 Raw Edit

Lua script engine

public text v1 · immutable
#802653 ·published 2007-11-30 14:31 UTC
rendered paste body
//To run a Lua scripts, it calls sl_Doscript_blargs, which in turn calls sl_doscript_stackargs.
// TODO: pcl functions like dialog and menu should accept an npc parameter!
#include "sl.h"
#include <lauxlib.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include "clif.h"
#include <assert.h>
#include <stdarg.h>
#include <sys/stat.h>
#include "pc.h"
#include "mob.h"
#include "itemdb.h"
#include "map.h"
#include "socket.h"
#include "clan_db.h"
#include "mmo.h"
#include "malloc.h"

#define sl_redtext(text) "\033[31;1m" text "\033[0m"
#define sl_err(text) printf(sl_redtext("Lua error:") " %s\n", text)
#define sl_err_print(state) sl_err(lua_tostring(state, -1))
// accessors should return 1 if the attribute was handled; otherwise an error will be raised
typedef int (*typel_getattrfunc)(lua_State *, void * /* self */, char * /* attrname */);
typedef int (*typel_setattrfunc)(lua_State *, void * /* self */, char * /*attrname */);
typedef int (*typel_initfunc)(lua_State *, void * /* self */, int /* dataref */, void * /* param */);
typedef struct typel_class_ {
	// an luaL_ref reference to the prototype table for this class. the prototype table holds
	// the functions for this class.
	int protoref;
	char *name;
	typel_getattrfunc getattr;
	typel_setattrfunc setattr;
	typel_initfunc init;
	// remember when implementing the ctor that the first argument will always be the class
	// however, luaL_argerror uses normal indices; as in 1 still refers to the first real argument
	lua_CFunction ctor;
} typel_class;
typedef struct typel_inst_ {
	typel_class *type;
	int dataref;
	void *self;
} typel_inst;
int typel_mtindex(lua_State *);
int typel_mtnewindex(lua_State *);
int typel_mtgc(lua_State *);
int typel_mtref;
// TODO: actually use this!
#define sl_ensureasync(state) \
	if(state == sl_gstate) { luaL_error(state, "this function must be called from a coroutine; " \
		"that is, the calling method must be marked with async()"); }

// TODO: do we even need this anymore?
#define typel_err_invalidattr(state, type, attrname) \
	luaL_error(state, "'%s' object has no attribute '%s'", type->name, attrname)
void typel_staticinit();
void typel_staticdestroy(); // TODO: this should unref typel_mtref?
typedef int (*typel_func)(lua_State *, void * /* self */);
#define typel_topointer(state, index) (((typel_inst *)lua_touserdata(state, index))->self)
#define typel_check(state, index, type) (((typel_inst *)lua_touserdata(state, index))->type == type)
int typel_boundfunc(lua_State *);
void typel_pushinst(lua_State *, typel_class *, void *, void *);
typel_class typel_new(char *, lua_CFunction);
void typel_extendproto(typel_class *, char *, typel_func);
#define sl_memberarg(x) (x + 1)
#define sl_memberself 1

int bll_getattr(lua_State *, struct block_list *, char *attrname);
int bll_setattr(lua_State *, struct block_list *, char *attrname);
void bll_pushinst(lua_State *, struct block_list *, void *);

#define pcl_pushinst(state, sd) typel_pushinst(state, &pcl_type, sd, 0)
typel_class pcl_type;
void pcl_staticinit();
#define regl_pushinst(state, sd) typel_pushinst(state, &regl_type, sd, 0)
typel_class regl_type;
void regl_staticinit();
#define fll_pushinst(state,fl) typel_pushinst(state, &fll_type, fl, 0)
typel_class fll_type;
void fll_staticinit();
#define mapregl_pushinst(state,sd) typel_pushinst(state,&mapregl_type,sd,0)
typel_class mapregl_type;
void mapregl_staticinit();
#define mobl_pushinst(state, mob) typel_pushinst(state, &mobl_type, mob, 0)
typel_class mobl_type;
void mobl_staticinit();
#define npcl_pushinst(state, nd) typel_pushinst(state, &npcl_type, nd, 0)
typel_class npcl_type;
void npcl_staticinit();
#define iteml_pushinst(state, item) typel_pushinst(state, &iteml_type, item, 0)
typel_class iteml_type;
void iteml_staticinit();
#define biteml_pushinst(state, bitem) typel_pushinst(state, &biteml_type, bitem, 0)
typel_class biteml_type;
void biteml_staticinit();
#define SL_EXPOSE_ENUM(val) lua_pushnumber(sl_gstate, val); lua_setglobal(sl_gstate, #val)
#define sl_pushref(state, ref) lua_rawgeti(state, LUA_REGISTRYINDEX, ref)
void sl_checkargs(lua_State *, char *fmt);
void sl_loaddir(char *);
int sl_async(lua_State *);
int sl_async_done(lua_State *);
void sl_async_freeco(struct map_sessiondata *);
void sl_async_resume(struct map_sessiondata *, int);
int bll_spawn(lua_State *state, struct block_list* bl) {
	sl_checkargs(state,"nnnn");
	mobspawn_onetime(lua_tonumber(state,sl_memberarg(1)),
		bl->m,lua_tonumber(state,sl_memberarg(2)),
		lua_tonumber(state,sl_memberarg(3)),
		lua_tonumber(state,sl_memberarg(4)));
	return 0;
}
void bll_getobjects_helper(struct block_list *bl, va_list ap) {
	lua_State *state = va_arg(ap, lua_State *);
	
	bll_pushinst(state, bl, 0);
	lua_rawseti(state, -2, lua_objlen(state, -2) + 1);
}
int bll_getobjects(lua_State *state, void *self, int area) {
	sl_checkargs(state, "n");
	struct block_list *bl=(struct block_list*)self;
/*#define NUMBER_FIELD(name) \
	lua_getfield(state, sl_memberself, #name); \
	int name = lua_tonumber(state, -1); \
	lua_pop(state, 1)

	NUMBER_FIELD(m);
	NUMBER_FIELD(x);
	NUMBER_FIELD(y);
#undef NUMBER_FIELD*/
	
	lua_newtable(state);
	int type = lua_tonumber(state, sl_memberarg(1));
	map_foreachinarea(bll_getobjects_helper, bl->m, bl->x, bl->y, area, type, state);
	return 1;
}
int bll_getobjects_cell(lua_State *state, void *self) {
	sl_checkargs(state, "nnnn");
	int m = lua_tonumber(state, sl_memberarg(1)),
	    x = lua_tonumber(state, sl_memberarg(2)),
	    y = lua_tonumber(state, sl_memberarg(3)),
	    type = lua_tonumber(state, sl_memberarg(4));
	lua_newtable(state);
	map_foreachincell(bll_getobjects_helper, m, x, y, type, state);
	return 1;
}
int bll_getobjects_area(lua_State *state, void *self) {
	return bll_getobjects(state, self, AREA);
}
int bll_getobjects_samemap(lua_State *state, void *self) {
	return bll_getobjects(state, self, SAMEMAP);
}
int bll_sendanim(lua_State *state, void *self) {
	sl_checkargs(state, "n");
	struct block_list *bl = (struct block_list*)self;
	
	int anim = lua_tonumber(state, sl_memberarg(1));
	
	map_foreachinarea(clif_sendanimation, bl->m, bl->x, bl->y, AREA, BL_PC, anim, bl);
	return 0;
}
int bll_sendaction(lua_State *state,void *self) {
	sl_checkargs(state,"nn");
	struct block_list *bl=(struct block_list*)self;
	int action=lua_tonumber(state,sl_memberarg(1));
	int time=lua_tonumber(state,sl_memberarg(2));

	clif_sendaction(bl,action,time,0);
	return 0;
}
int bll_getusers(lua_State *state, void *self) {
	struct map_sessiondata *tsd;
	
	//struct block_list *bl= (struct block_list*)self;
	int i;
	lua_newtable(state);
	for(i=0;i<fd_max;i++) {
		if(session[i] && (tsd=session[i]->session_data)) {
			
		bll_pushinst(state, &tsd->bl, 0);
		lua_rawseti(state, -2, lua_objlen(state, -2) + 1);
		}

	}
	return 1;
}
int getobjectsmap(lua_State *state) {
	int m=lua_tonumber(state,1);
	int type=lua_tonumber(state,2);
	int x;
	struct mobspawn_data *te;
	lua_newtable(state);
	//printf("Map: %d\n",type);
	//map_foreachinarea(bll_getobjects_helper, m, 1, 1, SAMEMAP, type, state);
	for(x=1;x<map[m].block_mob_count+1;x++) {
		te=map[m].block_mob[x];
		bll_pushinst(state,&te->bl,0);
		lua_rawseti(state,-2,x+1);
	}
	return 1;
}
void sl_checkargs(lua_State *state, char *fmt) {
	int narg;
	for(narg = 1; fmt[narg - 1]; ++narg) {
		int expectedtype = LUA_TNIL, gottype = lua_type(state, sl_memberarg(narg));
		switch(fmt[narg - 1]) {
		case 'n': expectedtype = LUA_TNUMBER; break;
		case 'b': expectedtype = LUA_TBOOLEAN; break;
		case 't': expectedtype = LUA_TTABLE; break;
		case 's': expectedtype = LUA_TSTRING; break;
		case 'f': expectedtype = LUA_TFUNCTION; break;
		case 'u': expectedtype = LUA_TUSERDATA; break;
		}
		if(gottype != expectedtype) {
			char message[512];
			message[0] = 0;
			sprintf(message, "%s expected, got %s",
				lua_typename(state, expectedtype), lua_typename(state, gottype));
			luaL_argerror(state, sl_memberarg(narg), message);
		}
	}
}
int sl_exec_redirectio(lua_State *state) {
	struct map_sessiondata *sd = lua_touserdata(state, lua_upvalueindex(1));
	char *msg = lua_tostring(state, 1);
	int msglen = lua_objlen(state, 1);
	clif_sendwisp(sd, "lua", msg, msglen);
	return 0;
}
int sl_luasize(struct map_sessiondata* sd) {
	char buf[255];

	sprintf(buf,"LUA is using %u KB",lua_gc(sl_gstate,LUA_GCCOUNT,0));
	clif_sendminitext(sd,buf,0);
	return 0;
}

int getobject(lua_State *state) {
	//sl_checkargs(state,"nnn");
	int m=lua_tonumber(state,1);
	int x=lua_tonumber(state,2);
	int y=lua_tonumber(state,3);
	if(map_isloaded(m)) {
		lua_pushnumber(state,map[m].obj[x+y*map[m].xs]);
	} 

	return 1;
}
int sl_updatepeople(struct block_list *bl, va_list ap) {
	struct map_sessiondata *sd;

	nullpo_ret(0,sd=(struct map_sessiondata*)bl);

	pc_warp(sd,sd->bl.m,sd->bl.x,sd->bl.y);
	return 0;
}
int setpostcolor(lua_State *state) {
	int board=lua_tonumber(state,1);
	int post=lua_tonumber(state,2);
	int color=lua_tonumber(state,3);
	map_changepostcolor(board,post,color);
}
int setobject(lua_State *state) {
	//sl_checkargs(state,"nnnn");
	int m=lua_tonumber(state,1);
	int x=lua_tonumber(state,2);
	int y=lua_tonumber(state,3);
	int newnum=lua_tonumber(state,4);
	if(map_isloaded(m)) {
		map[m].obj[x+y*map[m].xs]=newnum;
		map_foreachinarea(sl_updatepeople,m,x,y,AREA,BL_PC);
	} 

	return 0;
}

int setpass(lua_State *state) {
	int m=lua_tonumber(state,1);
	int x=lua_tonumber(state,2);
	int y=lua_tonumber(state,3);
	int newnum=lua_tonumber(state,4);
	if(map_isloaded(m)) {
		map[m].pass[x+y*map[m].xs]=newnum;
		map_foreachinarea(sl_updatepeople,m,x,y,AREA,BL_PC);
	}
	return 0;
}
int getpass(lua_State *state) {
	int m=lua_tonumber(state,1);
	int x=lua_tonumber(state,2);
	int y=lua_tonumber(state,3);
	if(map_isloaded(m)) {
		lua_pushnumber(state,map[m].pass[x+y*map[m].xs]);
	}
	return 1;
}
void sl_exec(struct map_sessiondata *sd, char *str) {
#define sl_exec_err() \
	char *msg = lua_tostring(sl_gstate, -1); \
	int msglen = lua_objlen(sl_gstate, -1); \
	clif_sendwisp(sd, "lua-error", msg, msglen)

	if(luaL_loadstring(sl_gstate, str) != 0) {
		sl_exec_err();
		lua_pop(sl_gstate, 1);
		return;
	}
	lua_newtable(sl_gstate); // the environment table
	lua_pushlightuserdata(sl_gstate, sd);
	lua_pushcclosure(sl_gstate, sl_exec_redirectio, 1);
	lua_setfield(sl_gstate, -2, "print"); // set the new print
	lua_newtable(sl_gstate); // the metatable for the environment
	lua_pushvalue(sl_gstate, LUA_GLOBALSINDEX);
	lua_setfield(sl_gstate, -2, "__index"); // set __index = _G
	lua_setmetatable(sl_gstate, -2);
	lua_setfenv(sl_gstate, -2);
	if(lua_pcall(sl_gstate, 0, 0, 0) != 0) {
		sl_exec_err();
		lua_pop(sl_gstate, 1); // pop the error string
		return;
	}
#undef sl_exec_err
}
void sl_init() {
	int i,count=0;
	sl_gstate = lua_open();
	luaL_openlibs(sl_gstate);
	
	//lua_gc(sl_gstate,LUA_GCSTOP,0); //TEMPORARILY IN..THIS MAKES YIELD WORK
	typel_staticinit();
	pcl_staticinit();
	regl_staticinit();
	mapregl_staticinit();
	mobl_staticinit();
	npcl_staticinit();
	iteml_staticinit();
	biteml_staticinit();
	fll_staticinit();

	{
		SL_EXPOSE_ENUM(MOB_ALIVE);
		SL_EXPOSE_ENUM(MOB_DEAD);
		SL_EXPOSE_ENUM(MOB_HIT);
		SL_EXPOSE_ENUM(MOB_AGGRESSIVE);
		SL_EXPOSE_ENUM(MOB_STATIONARY);
		SL_EXPOSE_ENUM(MOB_NORMAL);
	}
	{
		SL_EXPOSE_ENUM(BL_PC);
		SL_EXPOSE_ENUM(BL_NPC);
		SL_EXPOSE_ENUM(BL_ITEM);
		SL_EXPOSE_ENUM(BL_MOB);
		SL_EXPOSE_ENUM(BL_NUL);
		
	}
	{
		SL_EXPOSE_ENUM(EQ_WEAP);
		SL_EXPOSE_ENUM(EQ_ARMOR);
		SL_EXPOSE_ENUM(EQ_SHIELD);
		SL_EXPOSE_ENUM(EQ_HELM);
		SL_EXPOSE_ENUM(EQ_RIGHT);
		SL_EXPOSE_ENUM(EQ_LEFT);
		SL_EXPOSE_ENUM(EQ_SCRIPT1);
		SL_EXPOSE_ENUM(EQ_SCRIPT2);
		SL_EXPOSE_ENUM(EQ_FACEACC);
		SL_EXPOSE_ENUM(EQ_CROWN);
		SL_EXPOSE_ENUM(EQ_MANTLE);
		SL_EXPOSE_ENUM(EQ_NECKLACE);
		SL_EXPOSE_ENUM(EQ_BOOTS);
		SL_EXPOSE_ENUM(EQ_COAT);
	}
	
	//lua_newtable(sl_gstate);
	/*for(i=0;i<65535;i++) {
		if(map_isloaded(i)) {
			lua_pushnumber(sl_gstate,i);
			lua_rawseti(sl_gstate,-2,count+1);
			count++;
		}
	}
	*/
	//lua_setglobal(sl_gstate,"maps");

	lua_register(sl_gstate, "_async", sl_async);
	lua_register(sl_gstate, "_asyncDone", sl_async_done);
	
	//lua_pushcclosure(sl_gstate,getobjectsmap,1);
	lua_register(sl_gstate,"getObjectsMap",getobjectsmap);
	lua_register(sl_gstate,"getObject",getobject);
	lua_register(sl_gstate,"setObject",setobject);
	lua_register(sl_gstate,"setPass",setpass);
	lua_register(sl_gstate,"getPass",getpass);
	lua_register(sl_gstate,"setPostColor",setpostcolor);
	// make sure to load the sys.lua file before anything else!
	if(luaL_dofile(sl_gstate, "./lua/sys.lua")) {
		sl_err_print(sl_gstate);
		return;
	}

	sl_reload();
}
void sl_loaddir(char *dirpath) {
	DIR *dir = opendir(dirpath);
	struct dirent *dir_entry;
	char path[512];
	char dirpath_tail = dirpath[strlen(dirpath) - 1];
	int dirpath_hasslash = dirpath_tail == '/' || dirpath_tail == '\\';
	while(0 != (dir_entry = readdir(dir))) {
		char *filename = dir_entry->d_name;
		int filename_len = strlen(filename);
		// ignore special files
		if(!strcmp(filename, ".") || !strcmp(filename, "..") ||
			!strcmp(filename, ".svn") || !strcmp(filename, "sys.lua")) continue;
		strcpy(path, dirpath);
		if(!dirpath_hasslash) strcat(path, "/");
		strcat(path, dir_entry->d_name);
		struct stat dir_entry_stat;
		stat(path, &dir_entry_stat);
		if(S_ISDIR(dir_entry_stat.st_mode)) {
			sl_loaddir(path);
		} else if(S_ISREG(dir_entry_stat.st_mode)) {
			// only load files with the extension ".lua"
			if(filename_len < 4) continue;
			if(strcmp(&filename[filename_len - 4], ".lua")) continue;
			if(luaL_dofile(sl_gstate, path))
				sl_err_print(sl_gstate);
		}
	}
	closedir(dir);
}
void sl_reload() {
	sl_loaddir("./lua/");
}
void sl_fixmem() {
	lua_gc(sl_gstate,LUA_GCCOLLECT,0);
	return 0;
}
int sl_async_done(lua_State *state) {
	// free the coroutine
	struct map_sessiondata *sd = typel_topointer(state, 1);
	sl_async_freeco(sd);
}
void sl_async_freeco(struct map_sessiondata *sd) {

	if(!sd->coref) return 0;
	luaL_unref(sl_gstate, LUA_REGISTRYINDEX, sd->coref);
	sd->coref = 0;
}
void sl_async_resume(struct map_sessiondata *sd, int nargs) {
	unsigned int coref;
	struct map_sessiondata *nsd;
	if(!sd->coref) {
		nsd=map_id2sd(sd->coref_container);
		if(!nsd) return 0;
		
		coref=nsd->coref;
	} else {
		coref=sd->coref;
	}
	
	lua_State *costate;
	sl_pushref(sl_gstate, coref);
	if(lua_isthread(sl_gstate,-1)) {
		costate = lua_tothread(sl_gstate, -1);
		lua_pop(sl_gstate, 1); // pop the thread
	//printf("%d\n",lua_status(costate));
		lua_xmove(sl_gstate, costate, nargs);
		if(lua_resume(costate, nargs) == LUA_ERRRUN) {
			char *err = lua_tostring(costate, -1);
			lua_pop(costate, 1);
			sl_async_freeco(sd);
			sl_err(err);
		}
	} 
		
}
int sl_async(lua_State *state) {
	// first argument should be a player object, second argument should be a function to call
	struct map_sessiondata *sd = typel_topointer(state, 1);
	if(!sd) return 0;
	
	if(sd->coref) { clif_sendminitext(sd,"You are busy.",0); return 0; };
	
	lua_State *costate = lua_newthread(state);
	sd->coref = luaL_ref(state, LUA_REGISTRYINDEX);
	lua_pushvalue(state, 2); // push a copy of the function
	lua_xmove(state, costate, 1); // move the function into the coroutine state
	if(lua_resume(costate, 0) == LUA_ERRRUN) {
		lua_xmove(costate, state, 1);
		sl_async_freeco(sd);
		return lua_error(state);
	}
	return 0;
}
int sl_doscript_stackargs(char *root, char *method, int nargs) {
	int argsindex = lua_gettop(sl_gstate) - (nargs - 1), errhandler, i;
	;
	lua_getglobal(sl_gstate, "_errhandler");
	errhandler = lua_gettop(sl_gstate);
	lua_getglobal(sl_gstate, root);	
	if(lua_isnil(sl_gstate, -1)) {
		lua_pop(sl_gstate, 2 + nargs); // pop _errhandler, the table, and the args
		/*ntop=lua_gettop(sl_gstate);
		dif=ntop-top;

		printf("1Difference is %d\n",ntop-top);
		*/
		return 0;
	}
	lua_getfield(sl_gstate, -1, method);
	lua_replace(sl_gstate, -2); // essentially remove the table leaving only the field
	if(lua_isnil(sl_gstate, -1)) {
		
		lua_pop(sl_gstate, 2 + nargs); // pop _errhandler, the field, and the args
		/*ntop=lua_gettop(sl_gstate);
		dif=ntop-top;
		printf("2Difference is %d\n",ntop-top);
		*/
		return 0;
	}
	// push copies of the arguments onto the stack
	for(i = 0; i < nargs; ++i)
		lua_pushvalue(sl_gstate, argsindex + i);
	if(lua_pcall(sl_gstate, nargs, 0, errhandler) != 0) {
		sl_err_print(sl_gstate);
		
		lua_pop(sl_gstate, 1); // pop the error string
		/*ntop=lua_gettop(sl_gstate);
		dif=ntop-top;
		//if(dif<(nargs+2))
		printf("3Difference is %d\n",dif);*/
	}
	lua_pop(sl_gstate, nargs+1); // pop the original arguments, and _errhandler
	/*ntop=lua_gettop(sl_gstate);
	dif=ntop-top;
	printf("Difference is %d\n",dif);*/
	
	return 1;
}
int sl_doscript_blargs(char *root, char *method, int nargs, ...) {
	int i;
	struct block_list *bl=NULL;

	va_list argp;
	va_start(argp, nargs);
	for(i = 0; i < nargs; ++i) {
		bl=NULL;
		bl = va_arg(argp, struct block_list *);
		bll_pushinst(sl_gstate, bl, 0);
		//if(bl) newargs++;
	}
	va_end(argp);
	
	return sl_doscript_stackargs(root, method, nargs);
}
void sl_resumemenu(int selection, struct map_sessiondata *sd) {

	/*if(sd->coroutine) {
		if(lua_status(sd->coroutine)==LUA_YIELD) {
			lua_pushnumber(sd->coroutine, selection);
			lua_resume(sd->coroutine, 1);
		}
	}*/
	sd->in_menu=0;
	lua_pushnumber(sl_gstate, selection);
	sl_async_resume(sd, 1);
	
}
void sl_resumemenu2(int selection, int choice, struct map_sessiondata *sd) {
	if(selection==1) { //Quit
		sl_async_freeco(sd);
	}
	if(selection==2) { //Selected(Next)
		lua_pushnumber(sl_gstate,choice);
		sl_async_resume(sd,1);
	}
}
void sl_resumedialog(int choice, struct map_sessiondata *sd) {
	/*if(sd->coroutine) {
		if(lua_status(sd->coroutine)==LUA_YIELD) {
		if(choice == 0) lua_pushstring(sd->coroutine, "previous");
		else if(choice == 1) lua_pushstring(sd->coroutine, "quit");
		else if(choice == 2) lua_pushstring(sd->coroutine, "next");
		else lua_pushnil(sd->coroutine);
		lua_resume(sd->coroutine, 1);
		}
	}*/
	if(choice == 0) { lua_pushstring(sl_gstate, "previous"); }
	//else if(choice == 1) { lua_pushstring(sl_gstate, "quit"); }
	else if(choice == 1) { sl_async_freeco(sd); return; }
	else if(choice == 2) { lua_pushstring(sl_gstate, "next"); }
	else { lua_pushstring(sl_gstate,"quit"); }
	sl_async_resume(sd, 1);
}

void sl_resumebuy(int choice, struct map_sessiondata *sd) {
	/*if(sd->coroutine) {
		
		if((lua_status(sd->coroutine)==LUA_YIELD)) {
		lua_pushnumber(sd->coroutine,choice);
		lua_resume(sd->coroutine,1);
		} else {
			
			//sl_err_print(sd->coroutine);
		}
	}*/
	sd->in_menu=0;
	lua_pushnumber(sl_gstate, choice);
	sl_async_resume(sd, 1);
}


void sl_resumesell(int choice, struct map_sessiondata *sd) {
	/*if(sd->coroutine) {
		if(lua_status(sd->coroutine)==LUA_YIELD) {
		lua_pushnumber(sd->coroutine,choice);
		lua_resume(sd->coroutine,1);
		}
	}*/
	sd->in_menu=0;
	lua_pushnumber(sl_gstate, choice);
	sl_async_resume(sd, 1);
}
void sl_resumeinput(char* output, char* output2, struct map_sessiondata *sd) {
	/*if(sd->coroutine) {
		if(lua_status(sd->coroutine)==LUA_YIELD) {
		//lua_pushstring(sd->coroutine,output);
		lua_pushstring(sd->coroutine,output2);
		lua_resume(sd->coroutine,1);
		}
	}*/
	sd->in_menu=0;
	lua_pushstring(sl_gstate, output2);
	sl_async_resume(sd, 1);
}

void sl_resume(char* output,struct map_sessiondata *sd) {
	/*if(sd->coroutine) {
		if(lua_status(sd->coroutine)==LUA_YIELD) {
		lua_pushstring(sd->coroutine,output);
		lua_resume(sd->coroutine,1);
		}
	}*/
	lua_pushstring(sl_gstate, output);
	sl_async_resume(sd, 1);
}

int iteml_getattr(lua_State *, struct item_data *, char *);
int iteml_ctor(lua_State *);
void iteml_staticinit() {
	iteml_type = typel_new("Item", iteml_ctor);
	iteml_type.getattr = iteml_getattr;
}
int iteml_ctor(lua_State *state) {
	struct item_data *item = 0;
	if(lua_isnumber(state, 2))
		item = itemdb_search(lua_tonumber(state, 2));
	else if(lua_isstring(state, 2))
		item = itemdb_searchname(lua_tostring(state, 2));
	else luaL_argerror(state, 1, "expected string or number");
	if(!item) luaL_error(state, "could not find item in the database");
	iteml_pushinst(state, item);
	return 1;
}
int iteml_getattr(lua_State *state, struct item_data *item, char *attrname) {
	if(!strcmp(attrname, "vita")) lua_pushnumber(state, item->vita);
	else if(!strcmp(attrname, "mana")) lua_pushnumber(state, item->mana);
	else if(!strcmp(attrname, "dam")) lua_pushnumber(state, item->dam);
	else if(!strcmp(attrname, "price")) lua_pushnumber(state,item->price);
	else if(!strcmp(attrname, "sell")) lua_pushnumber(state,item->sell);
	else if(!strcmp(attrname, "name")) lua_pushstring(state,item->name);
	else if(!strcmp(attrname, "id")) lua_pushnumber(state,item->id);
	else if(!strcmp(attrname, "maxAmount")) lua_pushnumber(state,item->max_amount);
	else if(!strcmp(attrname, "maxDura")) lua_pushnumber(state,item->dura);
	else if(!strcmp(attrname, "type")) lua_pushnumber(state,item->type);
	else if(!strcmp(attrname, "depositable")) lua_pushboolean(state,item->depositable^1);
	else if(!strcmp(attrname, "exchangeable")) lua_pushboolean(state,item->exchangeable^1);
	else if(!strcmp(attrname, "droppable")) lua_pushboolean(state,item->droppable^1);
	else return 0; // the attribute was not handled
	return 1;
}

int biteml_getattr(lua_State *, struct item *, char *);
int biteml_setattr(lua_State *, struct item *, char *);
void biteml_staticinit() {
	biteml_type = typel_new("BoundItem", 0);
	biteml_type.getattr = biteml_getattr;
	biteml_type.setattr = biteml_setattr;
}
int biteml_setattr(lua_State *state, struct item *bitem, char *attrname) {
	if(!strcmp(attrname,"amount")) bitem->amount=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"dura")) bitem->dura=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"owner")) bitem->owner_id=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"realName")) strcpy(bitem->real_name,lua_tostring(state,-1));
	return 1;
}
int biteml_getattr(lua_State *state, struct item *bitem, char *attrname) {
	if(!strcmp(attrname, "amount")) lua_pushnumber(state, bitem->amount);
	else if(!strcmp(attrname, "dura")) lua_pushnumber(state, bitem->dura);
	else if(!strcmp(attrname, "owner")) lua_pushnumber(state,bitem->owner_id);
	else if(!strcmp(attrname, "realName")) lua_pushstring(state,bitem->real_name);
	else {
	struct item_data *item = itemdb_search(bitem->id); // NOTE: this may be slow...?
		assert(item);
		return iteml_getattr(state, item, attrname);
	}
	return 1;
}

int regl_getattr(lua_State *, struct map_sessiondata *, char *);
int regl_setattr(lua_State *, struct map_sessiondata *, char *);
struct global_reg *regl_findreg(struct map_sessiondata *, char *);
void regl_staticinit() {
	regl_type = typel_new("Registry", 0);
	regl_type.getattr = regl_getattr;
	regl_type.setattr = regl_setattr;
}
int regl_getattr(lua_State *state, struct map_sessiondata *sd, char *attrname) {
	lua_pushnumber(state, pc_readglobalreg(sd, attrname));
	return 1;
}
int regl_setattr(lua_State *state, struct map_sessiondata *sd, char *attrname) {
	pc_setglobalreg(sd, attrname, lua_tonumber(state, -1));
	return 1;
}

void typel_staticinit() {
	lua_newtable(sl_gstate); // the global metatable
	lua_pushcfunction(sl_gstate, typel_mtindex);
	lua_setfield(sl_gstate, -2, "__index");
	lua_pushcfunction(sl_gstate, typel_mtnewindex);
	lua_setfield(sl_gstate, -2, "__newindex");
	lua_pushcfunction(sl_gstate, typel_mtgc);
	lua_setfield(sl_gstate, -2, "__gc");
	typel_mtref = luaL_ref(sl_gstate, LUA_REGISTRYINDEX);
}
typel_class typel_new(char *name, lua_CFunction ctor) {
	typel_class type;
	memset(&type, 0, sizeof(typel_class));
	// TODO: expose the type object, not the prototype, to lua
	lua_newtable(sl_gstate); // the prototype table
	if(ctor) {
		lua_newtable(sl_gstate);
		lua_pushcfunction(sl_gstate, ctor);
		lua_setfield(sl_gstate, -2, "__call");
		lua_setmetatable(sl_gstate, -2);
		type.ctor = ctor;
	}
	type.protoref = luaL_ref(sl_gstate, LUA_REGISTRYINDEX);
	sl_pushref(sl_gstate, type.protoref); // expose the prototype table to lua
	lua_setglobal(sl_gstate, name);
	type.name = name;
	return type;
}
int typel_mtgc(lua_State *state) {
	
	
	typel_inst *inst = lua_touserdata(state, 1);
	//struct block_list *bl=(struct block_list*)inst->self;
	luaL_unref(state, LUA_REGISTRYINDEX, inst->dataref);
	//inst->dataref=0;
	//inst->self=0;
	//inst->type=0;
	//(inst->type);
	//FREE(inst);
	return 0;
}
void typel_pushinst(lua_State *state, typel_class *type, void *self, void *param) {
	typel_inst *inst = lua_newuserdata(state, sizeof(typel_inst));
	inst->self = self;
	inst->type = type;
	sl_pushref(state, typel_mtref); // set the metatable
	lua_setmetatable(state, -2);
	lua_newtable(state); // create a new data table and store a ref
	inst->dataref = luaL_ref(state, LUA_REGISTRYINDEX);
	if(type->init && inst->self) { type->init(state, inst->self, inst->dataref, param); }
	//else { luaL_error(state,"dataref no longer exists"); }
}
void typel_extendproto(typel_class *type, char *name, typel_func func) {
	sl_pushref(sl_gstate, type->protoref);
	lua_pushlightuserdata(sl_gstate, func);
	lua_pushcclosure(sl_gstate, typel_boundfunc, 1);
	lua_setfield(sl_gstate, -2, name);
	lua_pop(sl_gstate, 1); // pop the prototype table
}
int typel_boundfunc(lua_State *state) {
	typel_func wrapped = lua_touserdata(state, lua_upvalueindex(1));
	typel_inst *inst = lua_touserdata(state, 1); // the first parameter is the userdata object
	if(inst->self) {
		return wrapped(state, inst->self);
	}
}
int typel_mtindex(lua_State *state) {
	typel_inst *inst = lua_touserdata(state, 1);
	typel_class *type = inst->type;
	char *attrname = lua_tostring(state, 2);
	int result = 0;
	if(!inst->self) { lua_pushnil(state); return 1; }
	if(type->getattr)
		result = type->getattr(state, inst->self, attrname);
	if(!result) {
		// the attribute was not handled by the getattr method
		// next, try the prototype table
		sl_pushref(state, type->protoref);
		lua_getfield(state, -1, attrname);
		if(lua_isnil(state, -1)) {
			lua_pop(state, 2); // clean up the stack
			// then try the data table associated with the instance
			sl_pushref(state, inst->dataref);
			lua_getfield(state, -1, attrname);
			if(lua_isnil(state, -1)) {
				// there is no such attribute; push nil
				lua_pop(state, 1);
				lua_pushnil(state);
			}
		}
		lua_replace(state, -2);
	}
	return 1;
}
int typel_mtnewindex(lua_State *state) {
	typel_inst *inst = lua_touserdata(state, 1);
	typel_class *type = inst->type;
	char *attrname = lua_tostring(state, 2);
	if(!inst->self) { return 0; }
	int result = 0;
	if(type->setattr)
		result = type->setattr(state, inst->self, attrname);
	if(!result) { /* TODO: error */ }
	return 0;
}



int bll_deliddb(lua_State *state, struct block_list *bl) {
	map_deliddb(bl->id);
	return 0;
}

int bll_playsound(lua_State *state, struct block_list *bl) {
	int sound=lua_tonumber(state,sl_memberarg(1));
	clif_playsound(bl,sound);
	return 0;
}
int bll_talk(lua_State *state, struct block_list *bl) {
	sl_checkargs(state, "ns");
	int type=lua_tonumber(state,sl_memberarg(1));
	char *msg = lua_tostring(state, sl_memberarg(2));
	
	map_foreachinarea(clif_speak, bl->m, bl->x, bl->y, AREA, BL_PC, msg, bl,type);
	return 0;
}
int bll_permspawn(lua_State *state, struct block_list *bl) {
	return 0;

}
int bll_year(lua_State *state, struct block_list *bl) {
	lua_pushnumber(state,cur_year);
	return 1;
}
int bll_day(lua_State* state,struct block_list *bl)
{
	lua_pushnumber(state,cur_day);
	return 1;
}

int bll_time(lua_State* state, struct block_list *bl) {
	lua_pushnumber(state,cur_time);
	return 1;
}
int bll_sendside(lua_State *state, struct block_list* bl) {
	//printf("Done it?!\n");
	clif_sendside(bl);
	return 0;
}
int bll_delete(lua_State *state, struct block_list* bl) {
	if(bl->id) {
		map_deliddb(bl->id);
	}
	map_delblock(bl);
	if(bl->id>0) {
		clif_lookgone(bl);
	}
	FREE(bl);
}
int bll_addnpc(lua_State *state, struct block_list* bl) {
	struct npc_data *nd;
	CALLOC(nd,struct npc_data,1);
	strcpy(nd->name, lua_tostring(state,sl_memberarg(1)));
	strcpy(nd->npc_name, "nothing");
	nd->bl.type=BL_NPC;
	nd->bl.subtype=2;
	nd->bl.m=lua_tonumber(state,sl_memberarg(2));
	nd->bl.x=lua_tonumber(state,sl_memberarg(3));
	nd->bl.y=lua_tonumber(state,sl_memberarg(4));
	nd->bl.graphic_id=0;
	nd->bl.graphic_color=0;
	nd->bl.prev=NULL;
	nd->bl.next=NULL;
	map_addblock(&nd->bl);
}
int bll_dropitem(lua_State* state, struct block_list* bl) {
	int id;
	int amount;
	id=itemdb_id(lua_tostring(state,2));
	amount=lua_tonumber(state,3);

	mobdb_dropitem(id,amount,bl->m,bl->x,bl->y);
	return 0;
}
void bll_extendproto(typel_class *class) {
	typel_extendproto(class, "getObjectsInCell", bll_getobjects_cell);
	typel_extendproto(class, "getObjectsInArea", bll_getobjects_area);
	typel_extendproto(class, "getObjectsInSameMap", bll_getobjects_samemap);
	typel_extendproto(class, "sendAnimation",bll_sendanim);
	typel_extendproto(class, "getUsers",bll_getusers);
	typel_extendproto(class, "delFromIDDB",bll_deliddb);
	typel_extendproto(class, "playSound",bll_playsound);
	typel_extendproto(class, "sendAction",bll_sendaction);
	typel_extendproto(class, "talk",bll_talk);
	typel_extendproto(class, "spawn",bll_spawn);
	typel_extendproto(class, "addPermanentSpawn",bll_permspawn);
	typel_extendproto(class, "curYear",bll_year);
	typel_extendproto(class, "curDay",bll_day);
	typel_extendproto(class, "curTime",bll_time);
	typel_extendproto(class, "sendSide",bll_sendside);
	typel_extendproto(class, "delete",bll_delete);
	typel_extendproto(class, "addNPC",bll_addnpc);
	typel_extendproto(class, "dropItem",bll_dropitem);
}
void bll_pushinst(lua_State *state, struct block_list *bl, void *param) {
	if(!bl) { 
		lua_pushnil(state);
		return;
	}
	if(bl->type == BL_PC) {
		struct map_sessiondata *sd = map_id2sd(bl->id);
		typel_pushinst(state, &pcl_type, sd, param);
	} else if(bl->type == BL_MOB) {
		struct mobspawn_data *mob = (struct mobspawn_data *)bl;
		typel_pushinst(state, &mobl_type, mob, param);
	} else if(bl->type == BL_NPC) {
		struct npc_data *nd = (struct npc_data *)bl;
		typel_pushinst(state, &npcl_type, nd, param);
	} else if(bl->type == BL_ITEM) {
		struct flooritem_data *fl = (struct flooritem_data*)bl;
		typel_pushinst(state, &fll_type, fl, param);
	} else lua_pushnil(state); // TODO: should this be an error?
}

int bll_getattr(lua_State *state, struct block_list *bl, char *attrname) {
	if(!bl) return 0;
	if(!strcmp(attrname, "x")) lua_pushnumber(state, bl->x);
	else if(!strcmp(attrname, "y")) lua_pushnumber(state, bl->y);
	else if(!strcmp(attrname, "m")) lua_pushnumber(state, bl->m);
	else if(!strcmp(attrname, "blType")) lua_pushnumber(state,bl->type);
	else if(!strcmp(attrname,"ID")) lua_pushnumber(state,bl->id);
	else if(!strcmp(attrname,"pvp")) lua_pushboolean(state,map[bl->m].pvp);

	else return 0; // the attribute was not handled
	return 1;
}
int bll_setattr(lua_State *state, struct block_list *bl, char*attrname) {
	if(!bl) return 0;
	if(!strcmp(attrname,"pvp")) lua_toboolean(state,-1);
	else return 0;
	return 1;
}
int fll_getattr(lua_State *, struct flooritem_data *, char *);
int fll_setattr(lua_State *, struct flooritem_data *, char *);
int fll_move(lua_State *, struct flooritem_data *);
int fll_init(lua_State *, struct flooritem_data *, int, void *);
int fll_ctor(lua_State *);

void fll_staticinit() {
	fll_type = typel_new("FloorItem", fll_ctor);
	fll_type.getattr = fll_getattr;
	fll_type.setattr = fll_setattr;
	fll_type.init = fll_init;
	/*typel_extendproto(&mobl_type, "attack", mobl_attack);
	typel_extendproto(&mobl_type, "addHealth", mobl_addhealth);
	typel_extendproto(&mobl_type, "move",mobl_move);
	typel_extendproto(&mobl_type,"setDuration",mobl_setduration);
	typel_extendproto(&mobl_type,"moveIntent",mobl_moveintent);
	typel_extendproto(&mobl_type, "hasDuration",mobl_hasduration);
	typel_extendproto(&mobl_type,"removeHealth",mobl_removehealth);
	typel_extendproto(&mobl_type,"flushDuration",mobl_flushduration);
	typel_extendproto(&mobl_type,"durationAmount",mobl_durationamount);
	*/
	bll_extendproto(&mobl_type);
}
int fll_ctor(lua_State *state) {
	if(!lua_isnumber(state, 1)) luaL_argerror(state, 1, "expected number");
	struct flooritem_data *fl = (struct flooritem_data*)map_id2bl(lua_tonumber(state, 1));
	if(!fl) return 0;
	fll_pushinst(state, fl);
	return 1;
}
int fll_init(lua_State *state, struct flooritem_data *fl, int dataref, void *param) {
	sl_pushref(state, dataref);
	
	biteml_pushinst(state,&fl->data);
	lua_setfield(state,-2,"data");
	
	lua_pop(state, 1); // pop the data table
}
int fll_getattr(lua_State *state, struct flooritem_data *fl, char* attrname) {
	return bll_getattr(state,&fl->bl,attrname);
}
int fll_setattr(lua_State *state, struct flooritem_data *fl, char* attrname) {
	if(bll_setattr(state,&fl->bl,attrname)) return 1;
	else return 0;
}
int npcl_getattr(lua_State *, struct npc_data *, char *);

void npcl_staticinit() {
	npcl_type = typel_new("NPC", 0);
	npcl_type.getattr = npcl_getattr;
	bll_extendproto(&npcl_type);
}
int npcl_getattr(lua_State *state, struct npc_data *nd, char *attrname) {
	return bll_getattr(state, &nd->bl, attrname); }


int mobl_attack(lua_State *, struct mobspawn_data *);
int mobl_addhealth(lua_State *, struct mobspawn_data *);
int mobl_getattr(lua_State *, struct mobspawn_data *, char *);
int mobl_setattr(lua_State *, struct mobspawn_data *, char *);
int mobl_move(lua_State *, struct mobspawn_data *);
int mobl_init(lua_State *, struct mobspawn_data *, int, void *);
int mobl_ctor(lua_State *);
int mobl_setduration(lua_State *,struct mobspawn_data*);
int mobl_moveintent(lua_State*,struct mobspawn_data*);
int mobl_hasduration(lua_State*, struct mobspawn_data*);
int mobl_removehealth(lua_State*,struct mobspawn_data*);
int mobl_flushduration(lua_State*,struct mobspawn_data*);
int mobl_durationamount(lua_State*,struct mobspawn_data*);

void mobl_staticinit() {
	mobl_type = typel_new("Mob", mobl_ctor);
	mobl_type.getattr = mobl_getattr;
	mobl_type.setattr = mobl_setattr;
	mobl_type.init = mobl_init;
	typel_extendproto(&mobl_type, "attack", mobl_attack);
	typel_extendproto(&mobl_type, "addHealth", mobl_addhealth);
	typel_extendproto(&mobl_type, "move",mobl_move);
	typel_extendproto(&mobl_type,"setDuration",mobl_setduration);
	typel_extendproto(&mobl_type,"moveIntent",mobl_moveintent);
	typel_extendproto(&mobl_type, "hasDuration",mobl_hasduration);
	typel_extendproto(&mobl_type,"removeHealth",mobl_removehealth);
	typel_extendproto(&mobl_type,"flushDuration",mobl_flushduration);
	typel_extendproto(&mobl_type,"durationAmount",mobl_durationamount);

	bll_extendproto(&mobl_type);
}
int mobl_durationamount(lua_State* state,struct mobspawn_data* mob) {
	int x,id;
	id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	
	for(x=0;x<50;x++) {
		if(mob->da[x].id==id) {
			if(mob->da[x].duration>0) {
				lua_pushnumber(state,mob->da[x].duration);
				return 1;
			}
		}
	}
	lua_pushnumber(state,0);
	return 1;
}

int mobl_ctor(lua_State *state) {
	if(!lua_isnumber(state, 1)) luaL_argerror(state, 1, "expected number");
	struct mobspawn_data *mob = map_id2mob(lua_tonumber(state, 1));
	if(!mob) return 0;
	mobl_pushinst(state, mob);
	return 1;
}
int mobl_removehealth(lua_State *state, struct mobspawn_data *mob) {
	//struct map_sessiondata* sd=map_id2sd(lua_tonumber(state,sl_memberarg(1)));
	int damage=lua_tonumber(state,sl_memberarg(1));
	
	clif_send_mob_health(mob,damage,0);
	
	return 0;
}

int mobl_moveintent(lua_State *state, struct mobspawn_data *mob) {
	struct block_list* bl=map_id2bl(mob->target);
	nullpo_ret(0,bl);
	lua_pushnumber(state,move_mob_intent(mob,bl));
	return 1;
}

int mobl_setduration(lua_State *state,struct mobspawn_data *mob) {
	//sl_checkargs(state, "nn");
	int id,time,x;

	id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	time=lua_tonumber(state,sl_memberarg(2));
	
	for(x=0;x<50;x++) {
		if(mob->da[x].id==id) {
			mob->da[x].duration=time;
			
			return 0;
		} else if(mob->da[x].id==0) {
			mob->da[x].id=id;
			mob->da[x].duration=time;
			
			return 0;
		}
	}
	return 0;
	
	
}
int mobl_flushduration(lua_State *state, struct mobspawn_data *mob) {

	/*int x;

	for(x=0;x<50;x++) {
		if(mob->da[x].id>0) {
			//mob->da[x].time=0;
			//sl_doscript_blargs(magicdb_yname(mob->da[x].id),"uncast",1,&mob->bl);
			mob->da[x].duration=250;
		}
	}*/
	mob_flushmagic(mob);
	return 0;
}
int mobl_hasduration(lua_State *state, struct mobspawn_data* mob) {
	//sl_checkargs(state, "n");
	int x,id;
	id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	
	for(x=0;x<50;x++) {
		if(mob->da[x].id==id) {
			if(mob->da[x].duration>0) {
				lua_pushboolean(state,1);
				return 1;
			}
		}
	}
	lua_pushboolean(state,0);
	return 1;
}

int mobl_init(lua_State *state, struct mobspawn_data *mob, int dataref, void *param) {
	//int top=lua_gettop(state);
	//int ntop=0;

	sl_pushref(state, dataref);
	if(mob->target && param == 0) {
		// the param is used to stop infinite recursion
		/*struct block_list *bl = map_id2bl(mob->target);
		if(bl) {
			bll_pushinst(state, bl, 1);
			lua_setfield(state, -2, "target");
		}*/
	}
	//ntop=lua_gettop(state);
	//printf("Top is %d\n",ntop-top);
	lua_pop(state, 1); // pop the data table
}

int mobl_getattr(lua_State *state, struct mobspawn_data *mob, char *attrname) {
	if(bll_getattr(state, &mob->bl, attrname)) return 1;
	if(!strcmp(attrname,"state")) lua_pushnumber(state,mob->state);
	else if(!strcmp(attrname,"type")) lua_pushnumber(state,mobdb_type(mob->id));
	else if(!strcmp(attrname,"side")) lua_pushnumber(state,mob->side);
	//else if(!strcmp(attrname,"blType")) lua_pushnumber(state,mob->bl.type);
	else if(!strcmp(attrname,"name")) lua_pushstring(state,mobdb_name(mob->id));
	else if(!strcmp(attrname,"paralyzed")) lua_pushboolean(state,mob->paralyzed);
	else if(!strcmp(attrname,"blind")) lua_pushboolean(state,mob->blind);
	else if(!strcmp(attrname,"hit")) lua_pushnumber(state,mobdb_hit(mob->id));
	else if(!strcmp(attrname,"level")) lua_pushnumber(state,mobdb_level(mob->id));
	else if(!strcmp(attrname,"grace")) lua_pushnumber(state,mobdb_grace(mob->id));
	else if(!strcmp(attrname,"might")) lua_pushnumber(state,mobdb_might(mob->id));
	else if(!strcmp(attrname,"health")) lua_pushnumber(state,mob->current_vita);
	else if(!strcmp(attrname,"maxHealth")) lua_pushnumber(state,mobdb_getvita(mob->id));
	else if(!strcmp(attrname,"ac")) lua_pushnumber(state,mob->ac);
	else if(!strcmp(attrname,"baseAc")) lua_pushnumber(state,mobdb_baseac(mob->id));
	else if(!strcmp(attrname,"attacker")) lua_pushnumber(state,mob->attacker);
	else if(!strcmp(attrname,"confused")) lua_pushboolean(state,mob->confused);
	else if(!strcmp(attrname,"controlled")) lua_pushboolean(state,mob->controlled);
	else if(!strcmp(attrname,"controller")) lua_pushnumber(state,mob->controller);
	else if(!strcmp(attrname,"sleep")) lua_pushnumber(state,mob->sleep);
	else if(!strcmp(attrname,"target")) lua_pushnumber(state,mob->target);
	else if(!strcmp(attrname,"confuseTarget")) lua_pushnumber(state,mob->confused_target);
	else if(!strcmp(attrname,"deduction")) lua_pushnumber(state,mob->deduction);
	else if(!strcmp(attrname,"sound")) lua_pushnumber(state,mobdb_sound(mob->id));
	//else if(!strcmp(attrname,"attacker"
	//else if(!strcmp(attrname,"graphic"
	else return 0;

	return 1;
	
}
int mobl_setattr(lua_State *state, struct mobspawn_data *mob, char* attrname) {
	if(bll_setattr(state,&mob->bl,attrname)) return 1;
	if(!strcmp(attrname,"x")) mob->bl.x=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"y")) mob->bl.y=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"m")) mob->bl.m=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"side")) mob->side=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"time")) mob->time=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"paralyzed")) mob->paralyzed=lua_toboolean(state,-1);
	else if(!strcmp(attrname,"blind")) mob->blind=lua_toboolean(state,-1);
	else if(!strcmp(attrname,"health")) mob->current_vita=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"ac")) mob->ac=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"health")) mob->current_vita=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"attacker")) mob->attacker=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"confused")) mob->confused=lua_toboolean(state,-1);
	else if(!strcmp(attrname,"controlled")) mob->controlled=lua_toboolean(state,-1);
	else if(!strcmp(attrname,"controller")) mob->controller=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"sleep")) mob->sleep=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"target")) mob->target=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"confuseTarget")) mob->confused_target=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"deduction")) mob->deduction=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"state")) mob->state=lua_tonumber(state,-1);
	else return 0;

	return 1;
}

int mobl_attack(lua_State *state, struct mobspawn_data *mob) {
	sl_checkargs(state, "u");
	struct map_sessiondata *attacksd = typel_topointer(state, sl_memberarg(1));
	mob_attack(mob, attacksd);
	return 0;
}
int mobl_addhealth(lua_State *state, struct mobspawn_data *mob) {
	sl_checkargs(state, "n");
	// TODO: this bounds checking on the health should probably be factored out
	int addvita = lua_tonumber(state, sl_memberarg(1));
	int maxvita = mobdb_getvita(mob->id);
	mob->current_vita += addvita;
	if(mob->current_vita > maxvita) mob->current_vita = maxvita;
	if(mob->current_vita < 0) mob->current_vita = 0;
	return 0;
}

int mobl_move(lua_State *state, struct mobspawn_data *mob) {
	lua_pushboolean(state,move_mob(mob));
	return 1;
}

int pcl_addmagic(lua_State *, struct map_sessiondata *);
int pcl_addhealth(lua_State *, struct map_sessiondata *);
int pcl_resurrect(lua_State *, struct map_sessiondata *);
int pcl_warp(lua_State *, struct map_sessiondata *);
int pcl_useitem(lua_State *, struct map_sessiondata *);
int pcl_level(lua_State *, struct map_sessiondata *);
int pcl_sendminitext(lua_State*,struct map_sessiondata *);
int pcl_setduration(lua_State*,struct map_sessiondata *);
int pcl_dialog(lua_State *, struct map_sessiondata *);
int pcl_getattr(lua_State *, struct map_sessiondata *, char *);
int pcl_setattr(lua_State *, struct map_sessiondata *, char *);
int pcl_setaether(lua_State *, struct map_sessiondata *);
int pcl_hasduration(lua_State *, struct map_sessiondata *);
int pcl_addlegend(lua_State *, struct map_sessiondata *);
int pcl_buy(lua_State *, struct map_sessiondata *);
int pcl_input(lua_State *, struct map_sessiondata *);
int pcl_sell(lua_State *,struct map_sessiondata *);
int pcl_sell2(lua_State *,struct map_sessiondata *);
int pcl_sendstatus(lua_State*,struct map_sessiondata *);
int pcl_getinventoryitem(lua_State*,struct map_sessiondata *);
int pcl_getequippeditem(lua_State*,struct map_sessiondata *);
int pcl_removelegendbyname(lua_State*,struct map_sessiondata *);
int pcl_removelegendbycolor(lua_State*,struct map_sessiondata *);
int pcl_menu(lua_State *, void*);
int pcl_showhealth(lua_State *, struct map_sessiondata *);
int pcl_addclan(lua_State *, struct map_sessiondata *);
int pcl_updatestate(lua_State*, struct map_sessiondata *);
int pcl_ctor(lua_State *);
int pcl_hasequipped(lua_State*, struct map_sessiondata *);
int pcl_killcount(lua_State*, struct map_sessiondata *);
int pcl_killrank(lua_State*,struct map_sessiondata *);
int pcl_flushkills(lua_State*, struct map_sessiondata *);
int pcl_removeinventoryitem(lua_State*, struct map_sessiondata*);
int pcl_additem(lua_State*,struct map_sessiondata*);
int pcl_init(lua_State *, struct map_sessiondata *, int, void *);
int pcl_showboard(lua_State *, struct map_sessiondata*);
int pcl_hasitem(lua_State*, struct map_sessiondata*);
int pcl_addspell(lua_State*, struct map_sessiondata*);
int pcl_removespell(lua_State*, struct map_sessiondata*);
int pcl_broadcast(lua_State*, struct map_sessiondata*);
int pcl_mapselect(lua_State*, struct map_sessiondata*);
int pcl_hasspell(lua_State*, struct map_sessiondata*);
int pcl_flushduration(lua_State*,struct map_sessiondata*);
int pcl_hasspace(lua_State*,struct map_sessiondata*);
int pcl_deductarmor(lua_State*,struct map_sessiondata*);
int pcl_updateinv(lua_State*,struct map_sessiondata*);
int pcl_durationamount(lua_State*,struct map_sessiondata*);
int pcl_addguide(lua_State*,struct map_sessiondata*);
int pcl_delguide(lua_State*,struct map_sessiondata*);
int pcl_popup(lua_State*,struct map_sessiondata*);
int pcl_menu2(lua_State*, void*);
int pcl_powerboard(lua_State*, struct map_sessiondata*);

void pcl_staticinit() {
	pcl_type = typel_new("Player", pcl_ctor);
	pcl_type.getattr = pcl_getattr;
	pcl_type.setattr = pcl_setattr;
	pcl_type.init = pcl_init;
	typel_extendproto(&pcl_type, "addHealth", pcl_addhealth);
	typel_extendproto(&pcl_type, "addMagic", pcl_addmagic);
	typel_extendproto(&pcl_type, "menu", pcl_menu);
	typel_extendproto(&pcl_type, "resurrect", pcl_resurrect);
	typel_extendproto(&pcl_type, "sendMinitext",pcl_sendminitext);
	typel_extendproto(&pcl_type, "setDuration",pcl_setduration);
	typel_extendproto(&pcl_type, "dialog", pcl_dialog);
	typel_extendproto(&pcl_type, "setAether",pcl_setaether);
	typel_extendproto(&pcl_type, "hasDuration",pcl_hasduration);
	typel_extendproto(&pcl_type, "hasSpace",pcl_hasspace);
	typel_extendproto(&pcl_type, "flushDuration",pcl_flushduration);
	typel_extendproto(&pcl_type, "addLegend",pcl_addlegend);
	typel_extendproto(&pcl_type, "buy",pcl_buy);
	typel_extendproto(&pcl_type, "input",pcl_input);
	typel_extendproto(&pcl_type, "sell",pcl_sell);
	typel_extendproto(&pcl_type, "sell2",pcl_sell2);
	typel_extendproto(&pcl_type, "sendStatus",pcl_sendstatus);
	typel_extendproto(&pcl_type, "getInventoryItem",pcl_getinventoryitem);
	typel_extendproto(&pcl_type, "getEquippedItem",pcl_getequippeditem);
	typel_extendproto(&pcl_type, "removeLegendbyName",pcl_removelegendbyname);
	typel_extendproto(&pcl_type, "removeLegendbyColor",pcl_removelegendbycolor);
	typel_extendproto(&pcl_type, "warp",pcl_warp);
	typel_extendproto(&pcl_type, "showHealth",pcl_showhealth);
	typel_extendproto(&pcl_type, "addClan", pcl_addclan);
	typel_extendproto(&pcl_type, "updateState",pcl_updatestate);
    typel_extendproto(&pcl_type, "hasEquipped",pcl_hasequipped);
	typel_extendproto(&pcl_type, "killCount",pcl_killcount);
	typel_extendproto(&pcl_type, "killRank",pcl_killrank);
	typel_extendproto(&pcl_type, "flushKills",pcl_flushkills);
	typel_extendproto(&pcl_type, "removeItem",pcl_removeinventoryitem);
	typel_extendproto(&pcl_type, "addItem",pcl_additem);
	typel_extendproto(&pcl_type, "showBoard",pcl_showboard);
	typel_extendproto(&pcl_type, "hasItem",pcl_hasitem);
	typel_extendproto(&pcl_type, "addSpell",pcl_addspell);
	typel_extendproto(&pcl_type, "removeSpell",pcl_removespell);
	typel_extendproto(&pcl_type, "hasSpell",pcl_hasspell);
	typel_extendproto(&pcl_type, "broadcast",pcl_broadcast);
	typel_extendproto(&pcl_type, "mapSelection",pcl_mapselect);
	typel_extendproto(&pcl_type, "deductArmor",pcl_deductarmor);
	typel_extendproto(&pcl_type, "updateInv",pcl_updateinv);
	typel_extendproto(&pcl_type, "durationAmount",pcl_durationamount);
	typel_extendproto(&pcl_type, "addGuide",pcl_addguide);
	typel_extendproto(&pcl_type, "delGuide",pcl_delguide);
	typel_extendproto(&pcl_type, "popUp",pcl_popup);
	typel_extendproto(&pcl_type, "menu2",pcl_menu2);
	typel_extendproto(&pcl_type, "powerBoard",pcl_powerboard);
	bll_extendproto(&pcl_type);
}
int pcl_menu2(lua_State *state, void *self) {
	struct map_sessiondata *sd = (struct map_sessiondata*)self;
	sl_checkargs(state, "st");
	int size = lua_objlen(state, sl_memberarg(2));
	char *menuopts[size + 1];
	lua_pushnil(state);
	while(lua_next(state, sl_memberarg(2)) != 0) {
		// key is at -2, value at -1
		int index = lua_tonumber(state, -2);
		menuopts[index] = lua_tostring(state, -1);
		lua_pop(state, 1);
	}
	char *topic = lua_tostring(state, sl_memberarg(1));
	clif_scriptmenu2(sd, 0, topic, menuopts, size);
	//sd->coroutine = state; TEMP
	return lua_yield(state, 0);
}
int pcl_popup(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"s");
	
	clif_popup(sd,lua_tostring(state,2));
	return 0;
}
int pcl_addguide(lua_State *state, struct map_sessiondata *sd) {
	int id=guidedb_id(lua_tostring(state,sl_memberarg(1)));
	int x;

	for(x=0;x<256;x++) {
		if(sd->status.guide[x]==id) return 0;
		if(sd->status.guide[x]==0) {
			sd->status.guide[x]=id;
			clif_sendguidespecific(sd,id);
			return 0;
		}
	}
	return 0;
}
int pcl_delguide(lua_State *state, struct map_sessiondata *sd) {
	int id=guidedb_id(lua_tostring(state,sl_memberarg(1)));
	int x;
	for(x=0;x<256;x++) {
		if(sd->status.guide[x]==id) {
			sd->status.guide[x]=0;
			return 0;
		}
	}
	return 0;
}
int pcl_durationamount(lua_State *state, struct map_sessiondata *sd) {
	int x,id;
	id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	
	for(x=0;x<200;x++) {
		if(sd->status.dura_aether[x].id==id) {
			if(sd->status.dura_aether[x].duration>0) {
				lua_pushnumber(state,sd->status.dura_aether[x].duration);
				return 1;
			}
		}
	}
	lua_pushnumber(state,0);
	return 1;
}
int pcl_updateinv(lua_State *state, struct map_sessiondata *sd) {
	pc_loaditem(sd);
	return 0;
}
int pcl_deductarmor(lua_State *state, struct map_sessiondata *sd) {
	clif_deductarmor(sd);
	return 0;
}

int pcl_flushduration(lua_State *state, struct map_sessiondata *sd) {
	int x;
	for(x=0;x<200;x++) {
		if(sd->status.dura_aether[x].id>0) {
			sd->status.dura_aether[x].duration=250;
			//sl_doscript_blargs(magicdb_yname(sd->status.dura_aether[x].id),"uncast",1,&sd->bl);
			clif_send_duration(sd,sd->status.dura_aether[x].id,0);
			//sd->status.dura_aether[x].id=0;
			
		}
	}
	return 0;
}
int pcl_broadcast(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"ns");
		
	clif_broadcast(lua_tostring(state,sl_memberarg(2)),lua_tonumber(state,sl_memberarg(1)));
	return 0;
}
int pcl_killcount(lua_State *state, struct map_sessiondata *sd) {
	int x;
	int id;

	
	id=mobdb_id(lua_tostring(state,sl_memberarg(1)));
	for(x=0;x<10;x++) {
		if(sd->status.quest[x].mob_id==id) {
			lua_pushnumber(state,sd->status.quest[x].amount);
			return 1;
		}
	}

	lua_pushnumber(state,0);
	return 1;
}
int pcl_killrank(lua_State *state, struct map_sessiondata *sd) {
	int x;
	int id;

	id=mobdb_id(lua_tostring(state,sl_memberarg(1)));
	for(x=0;x<10;x++) {
		if(sd->status.quest[x].mob_id==id) {
			lua_pushnumber(state,x+1);
			return 1;
		}
	}

	lua_pushnumber(state,0);
	return 1;
}
int pcl_flushkills(lua_State *state, struct map_sessiondata *sd) {
	int x;

	for(x=0;x<10;x++) {
		sd->status.quest[x].mob_id=0;
		sd->status.quest[x].amount=0;
	}
	return 0;
}

int pcl_showhealth(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"n");
	clif_send_pc_health(sd,1,lua_tonumber(state,sl_memberarg(1)));
	return 0;
}
int pcl_addclan(lua_State *state, struct map_sessiondata *sd) {
	struct clan_data* clan;
	sl_checkargs(state,"s");
	char* c_name=lua_tostring(state,sl_memberarg(1));
	clan=clandb_searchname(c_name);

	if(clan) {
		lua_pushboolean(state,0);
	} else {
		clandb_add(sd,c_name);
		lua_pushboolean(state,1);
	}
	return 1;
}
int pcl_hasequipped(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"t");
    int found=0;
	int count=0;
	int id;
	int x;
	lua_pushnil(state);
    
	while (lua_next(state, sl_memberarg(1)) != 0) {
		id=0;
		// key is at -2, value is at -1
		if(lua_isstring(state,-1)) {
			id=itemdb_id(lua_tostring(state,-1));
		} else {
			id=lua_tonumber(state,-1);
		}
		count++;

		for(x=0;x<15;x++) {
			if((sd->status.equip[x].id==id) && (id>0)) {
				found++;
				break;
			}
		}

		lua_pop(state, 1);
	}

	if(found==count) {
		lua_pushboolean(state,1);
	} else {
		lua_pushboolean(state,0);
	}
	return 1;
}
int pcl_ctor(lua_State *state) {
	struct map_sessiondata *sd;
	if(lua_isnumber(state, 2)) {
		int id = lua_tonumber(state, 2);
		sd = map_id2sd(id);
		if(!sd) return luaL_error(state, "invalid player id (%i)", id);
	} else if(lua_isstring(state, 2)) {
		char *name = lua_tostring(state, 2);
		sd = map_name2sd(name);
		if(!sd) return luaL_error(state, "invalid player name (%s)", name);
	} else luaL_argerror(state, 1, "expected string or number");
	pcl_pushinst(state, sd);
	return 1;
}
int pcl_setattr(lua_State *state, struct map_sessiondata *sd, char *attrname) {
	if(bll_setattr(state,&sd->bl,attrname)) return 1;
	if(!strcmp(attrname, "npcGraphic")) sd->npc_g = lua_tonumber(state, -1);
	else if(!strcmp(attrname, "npcColor")) sd->npc_gc = lua_tonumber(state, -1);
	else if(!strcmp(attrname, "title")) strcpy(sd->status.title,lua_tostring(state,-1));
	else if(!strcmp(attrname, "clanTitle")) strcpy(sd->status.clan_title,lua_tostring(state,-1));
	else if(!strcmp(attrname, "maxHealth")) sd->max_hp = lua_tonumber(state,-1);
	else if(!strcmp(attrname, "maxMagic")) sd->max_mp = lua_tonumber(state,-1);
	else if(!strcmp(attrname, "polearm")) sd->polearm=lua_tonumber(state,-1);
	else if(!strcmp(attrname, "rage")) sd->rage=lua_tonumber(state,-1);
	else if(!strcmp(attrname, "clan")) sd->status.clan_id=lua_tonumber(state,-1);
	else if(!strcmp(attrname, "gmLevel")) sd->status.gm_level=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"class")) sd->status.class=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"rank")) sd->status.subclass=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"health")) sd->status.hp=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"magic")) sd->status.mp=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"baseHealth")) sd->status.basehp=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"baseMagic")) sd->status.basemp=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"exp")) sd->status.exp=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"expCounter")) sd->status.expcounter=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"state")) sd->status.state=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"hair")) sd->status.hair=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"paralyzed")) sd->paralyzed=lua_toboolean(state,-1);
	else if(!strcmp(attrname,"blind")) { sd->blind=lua_toboolean(state,-1); clif_sendstatus2(sd); }
	else if(!strcmp(attrname,"backstab")) sd->backstab=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"flank")) sd->flank=lua_tonumber(state,-1); 
	else if(!strcmp(attrname,"ac")) sd->ac=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"dam")) sd->dam=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"hit")) sd->hit=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"might")) sd->might=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"will")) sd->will=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"grace")) sd->grace=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"boardDel")) sd->board_candel=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"boardWrite")) sd->board_canwrite=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"side")) sd->status.side=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"attackSpeed")) sd->attack_speed=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"enchant")) sd->enchanted=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"money")) sd->status.money=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"confused")) sd->confused=lua_toboolean(state,-1);
	else if(!strcmp(attrname,"skinColor")) sd->status.skin_color=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"target")) sd->target=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"deduction")) sd->deduction=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"hairColor")) sd->status.hair_color=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"face")) sd->status.face=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"faceColor")) sd->status.face_color=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"speed")) sd->speed=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"armorColor")) sd->status.armor_color=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"spouse")) sd->status.spouse=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"disguise")) sd->disguise=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"disguiseColor")) sd->disguise_color=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"attacker")) sd->attacker=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"invis")) sd->invis=lua_tonumber(state,-1);
	else if(!strcmp(attrname,"coContainer")) sd->coref_container=lua_tonumber(state,-1);
	//else if(!strcmp(attrname,"expCounter")) sd->status.
	else return 0;
	return 1;
}
int pcl_dialog(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state, "st");
	int previous = 0, next = 0;
	lua_pushnil(state);
     	while (lua_next(state, sl_memberarg(2)) != 0) {
		// key is at -2, value is at -1
		if(!strcmp(lua_tostring(state, -1), "previous")) previous = 1;
		else if(!strcmp(lua_tostring(state, -1), "next")) next = 1;
		lua_pop(state, 1);
	}
	
	char *msg = lua_tostring(state, sl_memberarg(1));
	
	//sd->coroutine = state; TEMP
	clif_scriptmes(sd, 0, msg, previous, next);
	return lua_yield(state, 0);
}
int pcl_init(lua_State *state, struct map_sessiondata *sd, int dataref, void *param) {
	//struct map_sessiondata *tsd;
	//int top=lua_gettop(state);
	//int ntop=0;
	int userc=0;
	//if(!sd) {
		//luaL_error(state,"cannot do that.");
		//sl_err_print(state);
	//	lua_pop(state,1);
	//	return 0;
	//}

	sl_pushref(state, dataref);
	regl_pushinst(state, sd);
	lua_setfield(state, -2, "registry");
	
	mapregl_pushinst(state,sd);
	lua_setfield(state,-2,"mapRegistry");
	/*if(sd->target) {
		if(sd->target == sd->bl.id) {
			lua_pushvalue(state, -2); // push a copy of the player object
			lua_setfield(state, -2, "target");
		} else if(param == 0) {
			// the param is used to stop infinite recursion
			struct block_list *bl = map_id2bl(sd->target);
			if(bl) {
				bll_pushinst(state, bl, 1);
				lua_setfield(state, -2, "target");
			}
		}
	}*/
	if(sd->group_count > 0) {
		int i;
		lua_newtable(state);
		for(i = 0; i < sd->group_count; ++i) {
			lua_pushnumber(state, sd->group[i]);
			lua_rawseti(state, -2, i + 1);
		}
		lua_setfield(state, -2, "group");
	}

	
	//lua_newtable(state);
	//map_foreachinarea(sl_mob_look,sd->bl.m,sd->bl.x,sd->bl.y,SAMEMAP,BL_MOB,sd);
	//lua_setfield(state,-2,"mobs");

	/*int i;
	lua_newtable(state);
	for(i=0;i<26;i++) {
		lua_pushnumber(state, sd->status.inventory[i].id);
		lua_rawseti(state, -2, i + 1);
	}
	lua_setfield(state,-2,"inventory");
*/
	//ntop=lua_gettop(state);
	//printf("Player Top is %d\n",ntop-top);
	lua_pop(state, 1); // pop the data table
}

int sl_mob_look(struct block_list *bl, va_list ap) {
	return 0;
}
int pcl_getattr(lua_State *state, struct map_sessiondata *sd, char *attrname) {
	if(bll_getattr(state, &sd->bl, attrname)) return 1;
	if(!strcmp(attrname, "health")) lua_pushnumber(state, sd->status.hp);
	else if(!strcmp(attrname, "magic")) lua_pushnumber(state, sd->status.mp);
	else if(!strcmp(attrname, "level")) lua_pushnumber(state, sd->status.level);
	else if(!strcmp(attrname, "name")) lua_pushstring(state, sd->status.name);
	else if(!strcmp(attrname, "title")) lua_pushstring(state, sd->status.title);
	else if(!strcmp(attrname,"maxHealth")) lua_pushnumber(state,sd->max_hp);
	else if(!strcmp(attrname,"maxMagic")) lua_pushnumber(state,sd->max_mp);
	else if(!strcmp(attrname,"rage")) {
		if(sd->rage) {
			lua_pushnumber(state,sd->rage);
		} else {
			lua_pushnumber(state,1);
		}
	}
	else if(!strcmp(attrname,"clanTitle")) lua_pushstring(state,sd->status.clan_title);
	else if(!strcmp(attrname,"polearm")) lua_pushnumber(state,sd->polearm);
	else if(!strcmp(attrname,"clan")) lua_pushnumber(state,sd->status.clan_id);
	else if(!strcmp(attrname,"gmLevel")) lua_pushnumber(state,sd->status.gm_level);
	else if(!strcmp(attrname,"class")) lua_pushnumber(state,sd->status.class);
	else if(!strcmp(attrname,"rank")) lua_pushnumber(state,sd->status.subclass);
	else if(!strcmp(attrname,"baseHealth")) lua_pushnumber(state,sd->status.basehp);
	else if(!strcmp(attrname,"baseMagic")) lua_pushnumber(state,sd->status.basemp);
	else if(!strcmp(attrname,"exp")) lua_pushnumber(state,sd->status.exp);
	else if(!strcmp(attrname,"expCounter")) lua_pushnumber(state,sd->status.expcounter);
	else if(!strcmp(attrname,"state")) lua_pushnumber(state,sd->status.state);
	else if(!strcmp(attrname,"hair")) lua_pushnumber(state,sd->status.hair);
	else if(!strcmp(attrname,"paralyzed")) lua_pushboolean(state,sd->paralyzed);
	else if(!strcmp(attrname,"blind")) lua_pushboolean(state,sd->blind);
	else if(!strcmp(attrname,"board")) lua_pushnumber(state,sd->board);
	else if(!strcmp(attrname,"boardDel")) lua_pushnumber(state,sd->board_candel);
	else if(!strcmp(attrname,"boardWrite")) lua_pushnumber(state,sd->board_canwrite);
	else if(!strcmp(attrname,"sex")) lua_pushnumber(state,sd->status.sex);
	else if(!strcmp(attrname,"side")) lua_pushnumber(state,sd->status.side);
	else if(!strcmp(attrname,"grace")) lua_pushnumber(state,sd->grace);
	else if(!strcmp(attrname,"might")) lua_pushnumber(state,sd->might);
	else if(!strcmp(attrname,"will")) lua_pushnumber(state,sd->will);
	else if(!strcmp(attrname,"ac")) lua_pushnumber(state,sd->ac);
	else if(!strcmp(attrname,"dam")) lua_pushnumber(state,sd->dam);
	else if(!strcmp(attrname,"hit")) lua_pushnumber(state,sd->hit);
	else if(!strcmp(attrname,"attackSpeed")) lua_pushnumber(state,sd->attack_speed);
	else if(!strcmp(attrname,"question")) lua_pushstring(state,sd->question);
	else if(!strcmp(attrname,"enchant")) lua_pushnumber(state,sd->enchanted);
	else if(!strcmp(attrname,"speech")) lua_pushstring(state,sd->speech);
	else if(!strcmp(attrname,"money")) lua_pushnumber(state,sd->status.money);
	else if(!strcmp(attrname,"confused")) lua_pushboolean(state,sd->confused);
	else if(!strcmp(attrname,"skinColor")) lua_pushnumber(state,sd->status.skin_color);
	else if(!strcmp(attrname,"target")) lua_pushnumber(state,sd->target);
	else if(!strcmp(attrname,"deduction")) lua_pushnumber(state,sd->deduction);
	else if(!strcmp(attrname,"speed")) lua_pushnumber(state,sd->speed);
	else if(!strcmp(attrname,"spouse")) lua_pushnumber(state,sd->status.spouse);
	else if(!strcmp(attrname,"disguise")) lua_pushnumber(state,sd->disguise);
	else if(!strcmp(attrname,"disguiseColor")) lua_pushnumber(state,sd->disguise_color);
	else if(!strcmp(attrname,"attacker")) lua_pushnumber(state,sd->attacker);
	else if(!strcmp(attrname,"invis")) lua_pushnumber(state,sd->invis);
	else if(!strcmp(attrname,"armorColor")) lua_pushnumber(state,sd->status.armor_color);
	//else if(!strcmp(attrname,"blType")) lua_pushnumber(state,sd->bl.type);
	//else if(!strcmp(attrname,"expCounter")) lua_pushnumber(state,sd->status.exp_counter);
	// TODO: else if(!strcmp(attrname, "clan")) lua_pushnumber(state, sd->status.clan);
	else return 0; // the attribute wasn't handled
	return 1;
}
int pcl_useitem(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state, "s");
	char *itemname = lua_tostring(state, sl_memberarg(1));
	int i;
	for(i = 0; i < 26; ++i) {
		if(!strcmpi(itemdb_name(sd->status.inventory[i].id), itemname)) {
			pc_useitem(sd, i);
			return 0;
		}
	}
	return 0;
}
int pcl_warp(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state, "nn");
	int m = lua_tonumber(state, sl_memberarg(1)),
	    x = lua_tonumber(state, sl_memberarg(2)),
	    y = lua_tonumber(state, sl_memberarg(3));
	pc_warp(sd, m, x, y);
}
int pcl_resurrect(lua_State *state, struct map_sessiondata *sd) {
	pc_res(sd);
	return 0;
}
int pcl_addhealth(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state, "n");
	pc_heal(sd, lua_tonumber(state, sl_memberarg(1)), 0);
	return 0;
}
int pcl_addmagic(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state, "n");
	pc_heal(0, sd, lua_tonumber(state, sl_memberarg(1)));
	return 0;
}



int pcl_menu(lua_State *state, void *self) {
	struct map_sessiondata *sd = (struct map_sessiondata*)self;
	sl_checkargs(state, "st");
	int size = lua_objlen(state, sl_memberarg(2));
	char *menuopts[size + 1];
	lua_pushnil(state);
	while(lua_next(state, sl_memberarg(2)) != 0) {
		// key is at -2, value at -1
		int index = lua_tonumber(state, -2);
		menuopts[index] = lua_tostring(state, -1);
		lua_pop(state, 1);
	}
	char *topic = lua_tostring(state, sl_memberarg(1));
	sd->in_menu=1;
	sd->co_timer=0;
	clif_scriptmenu(sd, 0, topic, menuopts, size);

	//sd->coroutine = state; TEMP
	return lua_yield(state, 0);
}

int pcl_sendminitext(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state, "s");
	char* msg;

	msg=lua_tostring(state,sl_memberarg(1));

	clif_sendminitext(sd,msg,strlen(msg));
	return 0;
}



int pcl_setduration(lua_State *state, struct map_sessiondata *sd) {
	//sl_checkargs(state, "nn");
	int id,time,x;

	id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	time=lua_tonumber(state,sl_memberarg(2));
	//printf("%d\n",id);
	for(x=0;x<200;x++) {
		if(sd->status.dura_aether[x].id==id) {
			sd->status.dura_aether[x].duration=time;
			clif_send_duration(sd,id,time/1000);
			return 0;
		} else if(sd->status.dura_aether[x].id==0) {
			sd->status.dura_aether[x].id=id;
			sd->status.dura_aether[x].duration=time;
			clif_send_duration(sd,id,time/1000);
			return 0;
		}
	}
	return 0;
}

int pcl_setaether(lua_State *state, struct map_sessiondata *sd) {
	
	int id;
	int time;
	int x;
	
	id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	time=lua_tonumber(state,sl_memberarg(2));
	
	for(x=0;x<200;x++) {
		if(sd->status.dura_aether[x].id==id) {
			sd->status.dura_aether[x].aether=time;
			clif_send_aether(sd,id,time/1000);
			return 0;
		}
		if(sd->status.dura_aether[x].id==0) { //blank
			sd->status.dura_aether[x].aether=time;
			if(!sd->status.dura_aether[x].duration) sd->status.dura_aether[x].duration=-1;
			sd->status.dura_aether[x].id=id;
			clif_send_aether(sd,id,time/1000);
			return 0;
		}
	}
	return 0;
}
int pcl_hasduration(lua_State *state, struct map_sessiondata *sd) {
	//sl_checkargs(state, "n");
	int x,id;
	id=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	
	for(x=0;x<50;x++) {
		if(sd->status.dura_aether[x].id==id) {
			if(sd->status.dura_aether[x].duration>0) {
				lua_pushboolean(state,1);
				return 1;
			}
		}
	}
	lua_pushboolean(state,0);
	return 1;
}
int pcl_addlegend(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"ssnn");
	int icon,color,x;
	int y=0;
	int found=0;

	icon=lua_tonumber(state,sl_memberarg(3));
	color=lua_tonumber(state,sl_memberarg(4));
	for(x=0;x<200;x++) {
		if(!strcmpi(sd->status.legends[x].name,lua_tostring(state,sl_memberarg(2)))) {
			y=1;
		} 
		if(y) {
			memset(sd->status.legends[x].text,0,64);
			memset(sd->status.legends[x].name,0,32);
			strcpy(sd->status.legends[x].text,sd->status.legends[x+1].text);
			strcpy(sd->status.legends[x].name,sd->status.legends[x+1].name);
			sd->status.legends[x].icon=sd->status.legends[x+1].icon;
			sd->status.legends[x].color=sd->status.legends[x+1].color;
		}
		
	}
	
	for(x=0;x<200;x++) {
		if(!strlen(sd->status.legends[x].text)) {
			memset(sd->status.legends[x].text,0,64);
			memset(sd->status.legends[x].name,0,32);
			strcpy(sd->status.legends[x].text,lua_tostring(state,sl_memberarg(1)));
			strcpy(sd->status.legends[x].name,lua_tostring(state,sl_memberarg(2)));
			sd->status.legends[x].icon=icon;
			sd->status.legends[x].color=color;
			return 0;
		}
	}
	/*for(x=0;x<200;x++) {
		if(strlen(sd->status.legends[x].text)<1) {
			strcpy(sd->status.legends[x].text,lua_tostring(state,sl_memberarg(1)));
			strcpy(sd->status.legends[x].name,lua_tostring(state,sl_memberarg(2)));
			sd->status.legends[x].icon=icon;
			sd->status.legends[x].color=color;
			return 0;
		}
		if(!strcmpi(sd->status.legends[x].name,lua_tostring(state,sl_memberarg(2)))) {
			strcpy(sd->status.legends[x].text,lua_tostring(state,sl_memberarg(1)));
			sd->status.legends[x].icon=icon;
			sd->status.legends[x].color=color;
			return 0;
		}
	}*/
	return 0;
}

int pcl_buy(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"stt");
	int x;
	int amount=lua_objlen(state,sl_memberarg(2));
	struct item_data *item[amount+1];
	int var2[amount+1];
	char* dialog;
	
	
	
	lua_pushnil(state);
	while(lua_next(state, sl_memberarg(2)) != 0) {
		// key is at -2, value at -1
		int index = lua_tonumber(state, -2);
		
			item[index-1] = itemdb_search(itemdb_id(lua_tostring(state, -1)));
		//var2[index-1]=1;
		lua_pop(state, 1);
	}
	
	lua_pushnil(state);
	while(lua_next(state, sl_memberarg(3)) != 0) {
		int index=lua_tonumber(state,-2);
		var2[index-1]=lua_tonumber(state,-1);
		lua_pop(state,1);
	}
	
	dialog=lua_tostring(state,sl_memberarg(1));
	sd->in_menu=1;
	sd->co_timer=0;
	clif_buydialog(sd,0,dialog,item,var2,amount);
	
	// sd->coroutine=state;//sd->coroutine=state; TEMP
	
	return lua_yield(state,0);
	
}

int pcl_mapselect(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"st");
	int index=0;
	int key=0;
	char* wm;
	int map_x0[255];
	int map_y0[255];
	char* map_name[255];
	int map_id[255];
	int map_x1[255];
	int map_y1[255];
	
	wm=lua_tostring(state,sl_memberarg(1));
	
	lua_pushnil(state);
	while(lua_next(state,sl_memberarg(2)) !=0) {
		if(key==6) {
			key=0;
			index++;
		}
		
		switch(key) {
		case 0:
			map_x0[index]=lua_tonumber(state,-1);
			break;
		case 1:
			map_y0[index]=lua_tonumber(state,-1);
			break;
		case 2:
			map_name[index]=lua_tostring(state,-1);
			break;
		case 3:
			map_id[index]=lua_tonumber(state,-1);
			break;
		case 4:
			map_x1[index]=lua_tonumber(state,-1);
			break;
		case 5:
			map_y1[index]=lua_tonumber(state,-1);
			break;
		}
		key++;
		lua_pop(state,1);
	}
	
	clif_mapselect(sd,wm,map_x0,map_y0,map_name,map_id,map_x1,map_y1,index);

	return 0;
}
int pcl_bank(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"s");
	int x;
	
	//for(x=0;x<sd->status.bank
}
int pcl_input(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"s");
	int count=lua_gettop(state);
	char* dialog=lua_tostring(state,sl_memberarg(1));
	
	lua_pushnil(state);
	
	//if(count==2) {
		//clif_input(sd,0,dialog,itemdb_name(lua_tonumber(state,2)));
	//} else {
	
	sd->in_menu=1;
	sd->co_timer=0;
	clif_input(sd,0,dialog,"");
	
		
	// sd->coroutine=state; TEMP
	
	return lua_yield(state,0);
}
	
int pcl_sell(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"st");
	char* dialog=lua_tostring(state,sl_memberarg(1));
	int amount=lua_objlen(state,sl_memberarg(2));
	int item[60];
	int taken[26];
	int count=0;
	int lastcount=0;
	char* temp;
	int x,y;
	lua_pushnil(state);
	while(lua_next(state,sl_memberarg(2))!=0) {
		int index=lua_tonumber(state,-2);
		temp=lua_tostring(state,-1);
		
		for(x=0;x<26;x++) {
			lastcount=0;
			if(sd->status.inventory[x].id==itemdb_id(temp)) {
				
				item[count]=x;
				//lastcount=count;
				count++;
				
			}
		}
		//printf("%d\n",count);
		//if(count>lastcount) item[count]=0;
		lua_pop(state,1);
	}
	sd->in_menu=1;
	sd->co_timer=0;
	// sd->coroutine=state; TEMP
	clif_selldialog(sd,dialog,item,count);
	return lua_yield(state,0);
}
int pcl_sell2(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"st");
	char* dialog=lua_tostring(state,sl_memberarg(1));
	int amount=lua_objlen(state,sl_memberarg(2));
	int item[60];
	int taken[26];
	int count=0;
	int lastcount=0;
	char* temp;
	int x,y;
	lua_pushnil(state);
	
	while(lua_next(state,sl_memberarg(2))!=0) {
		int index=lua_tonumber(state,-2);
		temp=lua_tostring(state,-1);
		
				
		item[count]=atoi(temp);
					
					count++;
				
				//lastcount=count;
				
				
			
		
		//printf("%d\n",count);
		//if(count>lastcount) item[count]=0;
		lua_pop(state,1);
	}
	sd->in_menu=1;
	sd->co_timer=0;
	// sd->coroutine=state; TEMP
	clif_selldialog(sd,dialog,item,count);
	return lua_yield(state,0);
}
int pcl_sendstatus(lua_State *state, struct map_sessiondata *sd) {
	clif_sendstatus(sd);
	return 0;
}

int pcl_getinventoryitem(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"n");
	int num=lua_tonumber(state,sl_memberarg(1));
	if(sd->status.inventory[num].id != 0)
		biteml_pushinst(state, &sd->status.inventory[num]);
	else lua_pushnil(state);
	return 1;
}
int pcl_addinventoryitem(lua_State *state, struct map_sessiondata *sd) {
	return 1;
}
int pcl_getequippeditem(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"n");
	int num=lua_tonumber(state,sl_memberarg(1));
	if(sd->status.inventory[num].id != 0)
		biteml_pushinst(state, &sd->status.equip[num]);
	else lua_pushnil(state);
}
int pcl_removelegendbyname(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"s");
	char* find=lua_tostring(state,sl_memberarg(1));
	int x,count=0;

	for(x=0;x<200;x++) {
		if(!strcmpi(sd->status.legends[x].name,find)) {
			count++;
		}
		if(x+count<200) {
			strcpy(sd->status.legends[x].text,sd->status.legends[x+count].text);
			strcpy(sd->status.legends[x].name,sd->status.legends[x+count].name);
			sd->status.legends[x].icon=sd->status.legends[x+count].icon;
			sd->status.legends[x].color=sd->status.legends[x+count].color;
		}
	}
	return 0;
}

int pcl_removelegendbycolor(lua_State *state, struct map_sessiondata *sd) {
	sl_checkargs(state,"n");
	int find=lua_tonumber(state,sl_memberarg(1));
	int x,count=0;

	for(x=0;x<200;x++) {
		if(sd->status.legends[x].color==find) {
			count++;
		}
		if(x+count<200) {
			strcpy(sd->status.legends[x].text,sd->status.legends[x+count].text);
			strcpy(sd->status.legends[x].name,sd->status.legends[x+count].name);
			sd->status.legends[x].icon=sd->status.legends[x+count].icon;
			sd->status.legends[x].color=sd->status.legends[x+count].color;
		}
	}
	return 0;
}

int pcl_updatestate(lua_State *state, struct map_sessiondata *sd) {
	map_foreachinarea(clif_updatestate,sd->bl.m,sd->bl.x,sd->bl.y,AREA,BL_PC,sd);
	return 0;
}

int pcl_removeinventoryitem(lua_State *state, struct map_sessiondata *sd) {
	//sl_checkargs(state,"");

	int id=0;
	int amount=0,max=0;
	int x;
	int count=0;
	
	
	id=itemdb_id(lua_tostring(state,sl_memberarg(1)));
	amount=lua_tonumber(state,sl_memberarg(2));
	max=amount;
	
	if(!id) { lua_pushboolean(state,0); return 1; }

	for(x=0;x<26;x++) {
		if(sd->status.inventory[x].id==id) {
			if((sd->status.inventory[x].amount<amount) && (sd->status.inventory[x].amount>0)) {
				count+=sd->status.inventory[x].amount;
				amount-=sd->status.inventory[x].amount;
				pc_delitem(sd,x,sd->status.inventory[x].amount,itemdb_type(sd->status.inventory[x].id));
				//valid[x]=1;
				if(count==max) {
					lua_pushboolean(state,1);
					return 1;
				}
				
			} else if(sd->status.inventory[x].amount>=amount){
				//if(!valid[x]) break;
				count+=amount;
				pc_delitem(sd,x,amount,itemdb_type(sd->status.inventory[x].id));
				lua_pushboolean(state,1);
				return 1;
			}
		}
	}
	

	lua_pushboolean(state,0);
	return 1;
}

int pcl_additem(lua_State *state, struct map_sessiondata* sd) {

	int id=0;
	int amount=0;
	int bound=0;
	struct item *fl;
	if(lua_gettop(state)==3) {
		bound=lua_toboolean(state,sl_memberarg(3));
	}
	CALLOC(fl,struct item,1);
	id=itemdb_id(lua_tostring(state,sl_memberarg(1)));
	amount=lua_tonumber(state,sl_memberarg(2));
	fl->id=id;
	fl->amount=amount;
	if(bound) {
	fl->owner_id=sd->bl.id;
	} else {
	fl->owner_id=0;
	}
	fl->dura=itemdb_dura(id);

	//map_additem(&fl->bl);
	if(!pc_additem(sd,fl)) {
		lua_pushboolean(state,1);
	} else {
		lua_pushboolean(state,0);
	}
	FREE(fl);
	return 1;
	
}

int pcl_showboard(lua_State *state, struct map_sessiondata* sd) {
	sl_checkargs(state,"n");
	sd->bcount=0;
	sd->board_popup=1;
	boards_showposts(sd,lua_tonumber(state,sl_memberarg(1)));
	return 0;
}

int pcl_hasitem(lua_State *state, struct map_sessiondata* sd) {
	int id=0;
	int amount=0,max=0;
	int x;
	int count=0;

	id=itemdb_id(lua_tostring(state,sl_memberarg(1)));
	amount=lua_tonumber(state,sl_memberarg(2));
	max=amount;

	for(x=0;x<26;x++) {
		if(sd->status.inventory[x].id==id) {
			if((sd->status.inventory[x].amount<amount) && (sd->status.inventory[x].amount>0)) {
				count+=sd->status.inventory[x].amount;
				//pc_delitem(sd,x,sd->status.inventory[x].amount,itemdb_type(sd->status.inventory[x].id));
				if(count==max) {
					lua_pushboolean(state,1);
					return 1;
				}
				amount--;
			} else if(sd->status.inventory[x].amount>=amount){
				count+=amount;
				//pc_delitem(sd,x,count,itemdb_type(sd->status.inventory[x].id));
				lua_pushboolean(state,1);
				return 1;
			}
		}
	}
	

	lua_pushboolean(state,0);
	return 1;
}

int pcl_addspell(lua_State* state, struct map_sessiondata *sd) {
	//sl_checkargs(state,"n");
	int spell=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	//char name[32];
	int x;
	//if(sscanf(line,"%d",&spell)<1)
	//	return -1;
	
	for(x=0;x<52;x++) {
		if(sd->status.skill[x]<=0) { //vacant spot
			sd->status.skill[x]=spell;
			pc_loadmagic(sd);
			break;
		}
		if(sd->status.skill[x]==spell) {
			break;
		}
	}

	return 0;

}
int pcl_hasspell(lua_State* state, struct map_sessiondata *sd) {
	//sl_checkargs(state,"n");
	int spell=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	//char name[32];
	int x;
	//if(sscanf(line,"%d",&spell)<1)
	//	return -1;
	
	for(x=0;x<52;x++) {
		if(sd->status.skill[x]==spell) {
			lua_pushboolean(state,1);
			return 1;
		}
	}

	lua_pushboolean(state,0);
	return 1;

}
int pcl_hasspace(lua_State* state, struct map_sessiondata *sd) {
	int id=itemdb_id(lua_tostring(state,sl_memberarg(1)));
	int amount=lua_tonumber(state,sl_memberarg(2));
	int namount=0;
	int a,x;
	if(pc_isinvenspace(sd,id)>=26) {
		lua_pushboolean(state,0);
		return 1;
	}
	namount=amount;
	for(x=0;x<26;x++) {
		//printf("%d\n",namount);
		if(namount==0) {
			lua_pushboolean(state,1);
			return 1;
		}
		if(sd->status.inventory[x].id==id) {
			if(sd->status.inventory[x].amount<itemdb_maxamount(id)) {
				//sd->status.inventory[x].amount+=nwamount;
				a=sd->status.inventory[x].amount+namount;
				if(itemdb_maxamount(id)<a) {
					namount=a-itemdb_maxamount(id);
				}
			}
			
		}
		if(sd->status.inventory[x].id<=0) {
				if(namount<=itemdb_maxamount(id)) {
					namount=0;
				} else {
					namount-=itemdb_maxamount(id);
				}
		}
	}

	if(namount==0) {
			lua_pushboolean(state,1);
			
	} else {
		lua_pushboolean(state,0);
		
	}
	return 1;

}
int pcl_removespell(lua_State* state, struct map_sessiondata *sd) {
	
	int spell=magicdb_id(lua_tostring(state,sl_memberarg(1)));
	int x;

	for(x=0;x<52;x++) {
		if(sd->status.skill[x]==spell) {
			sd->status.skill[x]=0;
			clif_removespell(sd,x);
			//pc_loadmagic(sd);
			return 0;
		}
	}

	return 0;
}
int pcl_powerboard(lua_State* state, struct map_sessiondata *sd) {
	clif_sendpowerboard(sd);
}

int mapregl_getattr(lua_State*,struct map_sessiondata*,char*);
int mapregl_setattr(lua_State*,struct map_sessiondata*,char*);


void mapregl_staticinit() {
	mapregl_type=typel_new("Mapregistry",0);
	mapregl_type.getattr=mapregl_getattr;
	mapregl_type.setattr=mapregl_setattr;
}

int mapregl_setattr(lua_State* state,struct map_sessiondata* sd,char* attrname) {
	map_setglobalreg(sd->bl.m,attrname,lua_tonumber(state,-1));
	return 1;
	
}

int mapregl_getattr(lua_State* state,struct map_sessiondata* sd,char* attrname) {
	lua_pushnumber(state,map_readglobalreg(sd->bl.m,attrname));
	return 1;
}